# Build with Airship Choose the path that fits your architecture: REST API references for server-to-server workflows, setup and integration guides for Mobile and Web SDKs, or setup and management guides for Email, SMS/MMS/RCS, and Open Channels. Use Airship's AI tools to bring the APIs and docs into your coding assistant. Use for technical integration questions involving SDKs, REST APIs, or channel setup. Covers Apple (iOS/macOS), Android, Web, React Native, Flutter, Cordova, Capacitor, Unity, Titanium, .NET, and Windows SDKs, plus REST API references and channel configuration for Email, SMS/MMS/RCS, and Open Channels. Always check SDK minimum versions before recommending a feature. ## Integrate with Airship REST APIs Integrate Airship from your server using REST APIs for messaging, audience operations, event streaming, and wallet workflows. ### Airship API Use Airship's REST APIs to send messages, manage audiences, automate workflows, and track performance. # Introduction > Airship provides a number of REST API endpoints collectively known as the Airship API Version 3, in support of our messaging product lines and related features. Version 3 is the current and only supported version of the Airship API. ## API Request Format All API requests are HTTP requests. For all requests with a body, the body may be in [JSON](https://www.json.org/json-en.html) format or other formats like CSV as specified for the endpoint. The proper Content-Type for JSON is `application/json` and the proper content type for CSV is `text/csv`. ### Date-Time Format All date-time values are represented as a string according to [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) in UTC. - The string must be in the format `YYYY-MM-dd['T']hh:mm:ss['Z']` where the `T` can be replaced by a space and the `Z` is optional. - A `T` separator is preferred but not required. It will be included in all date-time values generated by the API. For example: - 2023-11-13T09:42:30Z - 2023-11-13T09:42:30 - 2023-11-13 09:42:30Z - 2023-11-13 09:42:30 - A trailing time zone identifier or offset should not be included. - UTC is implicit. ### Color Format All color values are represented by a string format reminiscent of CSS color values used for web programming. The format is `#rrggbb`, a literal `#` character followed by 6 hexadecimal digits representing 3 values in the range `00` to `FF`. The values are red, green, and blue color components. ## API Response Format All API responses are HTTP responses, making use of appropriate HTTP response codes. When a body is present, it SHALL be in [JSON](https://www.json.org/json-en.html) format, except in certain cases where reporting data MAY be returned in CSV format. The body of all JSON responses SHALL consist of a single JSON object, which SHALL contain a boolean `ok` attribute indicating overall success or failure. When a request results in a return value containing multiple entities, they SHALL be contained in an array-valued attribute, the name of which MAY vary by endpoint. For example, `/api/tag` will return a list of tags in the `tags` attribute, while `/api/schedules` will return a list of schedules in the `schedules` attribute. The name of the response object attribute containing the list of returned entities SHALL be contained in the Data-Attribute HTTP header. ### Operation ID All API calls that create or modify resources, or cause side effects, SHALL generate an operation ID. An operation ID is an opaque unique string that identifies a single API call, and can be used to group multiple entities or side effects as related, in reporting and troubleshooting logs. For example, the batch push API call can be used to send multiple pushes in one call. Each push has a unique push ID, but they will all share a common operation ID. This enables roll-ups of multiple related operations (such as push to local time or push to language) and better end-to-end tracing in the push pipeline. Operation IDs are returned in the JSON body of the response, in the `operation_id` attribute of the root response object. An operation ID will be generated even for error responses. ### Response Codes The API makes use of standard HTTP response codes, with standard HTTP semantics. Response codes in the 200 range indicate success. Codes in the 400 range indicate errors of a correctable nature. Codes in the 500 range indicate system errors. This table lists general response definitions. Refer to the actual response definition per endpoint. | Response code | Description | |---|---| | **200 OK** | The payload was accepted. | | **201 Created** | An API request to create a new entity or entities was successful, and the entities were created. | | **202 Accepted** | An API request was successfully accepted into a processing queue to be processed later. | | **204 No Content** | An entity was successfully deleted. | | **400 Bad Request** | Parsing or validating the request failed. | | **401 Unauthorized** | Authentication information (the app key and secret) was either incorrect or missing. | | **403 Forbidden** | Authentication was correct, but the user does not have permission to access the requested API. This can happen if a feature is not included in the user's Airship plan. | | **404 Not Found** | A request was made for a non-existent entity. | | **405 Method Not Allowed** | A request was made using an HTTP method not supported by the endpoint. For example, sending a DELETE to /api/schedules. | | **406 Unacceptable** | The client requested a version of the API that cannot be satisfied, because no compatible version is currently deployed. | | **409 Conflict** | An entity could not be updated due to state conflict. | | **429 Too Many Requests** | A request was denied because the app made too many requests to an API in a short period of time. | ### Validation All requests must be validated. Proper validation at the API level can prevent invalid pushes from using resources in our delivery pipeline and educate API users about their own mistakes without involving Support. In the event of an error processing the request, the response body will contain one or more [error objects](/docs/developer/rest-api/ua/schemas/responses). Parsing errors, arising from syntactically invalid JSON, should return an `HTTP 400 Bad Request` response. Semantic errors, arising from requests that are syntactically valid but otherwise malformed (for example, missing required fields), should return an `HTTP 400` response, with a JSON body indicating details about the validation failure. Some examples of specific validation cases that cause pushes to be rejected with an `HTTP 400` error: - **Invalid attributes** — Any additional JSON keys that are not explicitly allowed by the spec will result in an HTTP 400 error, except where arbitrary keys are explicitly allowed (for example, the `extra` sections of a push payload). - **Unconfigured open platform** — Any open platform specified in the `device_types` array must be configured and active for the appKey. If the open platform is not configured, we will return an `HTTP 400`. - **Missing payload** — A push that specifies delivery to a platform but does not supply a payload for that platform is invalid. - **Device identifier/restriction mismatch** — A push that includes a device identifier in the audience selection but does not include the corresponding platform in the `device_types` specifier is invalid. - **Schedule times** — Requests to schedule pushes for times that have already passed will return an HTTP 400 response. However, requests to schedule local time pushes for a time that has elapsed in a local time zone will be accepted. - **Unsupported platform feature** — A push that includes features not supported on all platforms must explicitly target the supported platforms. Location is the only feature not supported across all platforms. This includes location expressions in predefined segments. Location pushes must specify `device_types` : [ `ios`, `android` ], or either iOS or Android explicitly. ### Pagination Some resource collections, such as tags and segments, may have a very large number of items, necessitating iterating through them in chunks (or pages) if an API consumer wishes to retrieve them all. **Request Parameters** There are two methods for pagination results: - `start` and `limit` - `page` and `page_size` Using a non-unique identifier for the `start` parameter is unsound and will not paginate correctly. For endpoints that support sorting, if sorting is applied to a non-unique field, a secondary sort on a unique field must be used internally to ensure stable pagination results. - `start` — Optional string or integer. Identifies the starting element for paginating results. It can be either a unique string identifier or a zero-based offset, depending on the API. - `limit` — Optional integer. The maximum number of elements to return. - `page` — Optional integer. Specifies which page to retrieve, starting with 1. - `page_size` — Optional integer. The number of elements to return per page. The last page may have fewer elements. - `sort` — Optional string. The name of the field to sort results by. This is not necessarily supported by all endpoints. - `order` — Optional `asc` or `desc`. If the `sort` parameter is available, this parameter may be used to specify the direction of the sort as ascending or descending. **Link Header** Collections of entities SHALL be paginated by specifying a start point and a limit on the number of returned items as parameters of the request. The response SHALL include the requested items and a link to the next page of results. A link to the previous page MAY also be included if the underlying service supports it. For example, the [Segments API](/docs/developer/rest-api/ua/operations/segments/) supports previous page links. The links SHALL be provided in the `Link` HTTP header, as per [RFC 5988 Web Linking](https://datatracker.ietf.org/doc/html/rfc5988.html), using the relations `next` and `prev`. **Count and Total** The number of items in the response SHALL be returned in the custom HTTP header `Count`, as well as in the `"count"` field of the response object. The total number of items in the collection MAY be returned in the custom HTTP header `Total-Count`, as well as in the `"total_count"` field of the response object, if the collection is countable and the total number of items is known. ## Version Syntax You must specify the version of the API you are using with the `Accept` HTTP header. If you do not specify an API version in the `Accept` header, a 406 is returned. The content type used is a vendor-specific media type (see [RFC 4288 Media Type Specifications and Registration Procedures](https://tools.ietf.org/html/rfc4288)) and must be specified as: `application/vnd.urbanairship+json; version=3`. ## Transport Layer Security As of October 6, 2020, Airship supports only Transport Layer Security (TLS) versions 1.2 and 1.3 in our APIs, in accordance with [PCI Security Standards Council](https://www.pcisecuritystandards.org/) recommendations. If your API integration uses TLS 1.0 or 1.1, [contact our Support team](https://support.airship.com) for assistance migrating to TLS 1.2 or 1.3. ### Certificate Pinning Certificate chains for Airship domains cannot be considered static. You should never pin or hardcode Intermediate or Root Certificate Authorities. Airship may rotate certificate chains at any time without notice, and pinning can cause service disruptions. This applies to all Airship-owned domains, not only the REST APIs. ## Delivery Speed Options The Airship push API is designed for extremely high throughput to ensure delivery to your entire audience as fast as possible. Depending on the size and/or complexity of your audience and the urgency of the message, you may find that you need to either slow down or speed up the delivery. To that end, we offer the following add-on services: Boost and Throttling. If you are interested in enabling Boost or Throttling, [contact Support](https://support.airship.com/). ### Boost Boost optimizes your segmented messages through parallel processing. Consider adding Boost if your notifications are extremely time-sensitive. Boost is a paid add-on. Contact your Account Manager for details. ### Throttling For less time-sensitive messages, our standard delivery speed may cause undue pressure on your internal systems or APIs, for example, when millions of users open your app at the same time. Use Throttling to tune delivery to a level that doesn't put strain on those systems. ### Complex segments can cause delays in processing When creating segments or pushes with logical expressions, keep in mind that one or more NOT statements may cause latency when sending notifications, as NOT operations are inherently more expensive to perform than OR or AND operations. For example, `tag_a AND NOT tag_b` is basically the same speed as `tag_a AND tag_b`, but just `NOT tag_b` is likely to be slower than just `tag_b`. Latency is more significant with larger audiences. We recommend using AND statements in place of NOT statements whenever possible as a best practice. ### Device changes can take a few minutes Some requests to register or unregister information about a device may take a few minutes to process before you are able to see the changes. Keep this in mind when performing PUT or POST requests. ## Base URL {#servers} Select the domain associated with your Airship project. | URL | Description | |-----|-------------| | `https://go.urbanairship.com` | The base URL for Airship's North American cloud site when using HTTP authentication | | `https://go.airship.eu` | The base URL for Airship's European cloud site when using HTTP authentication | | `https://api.asnapius.com` | The base URL for Airship's North American cloud site when using OAuth authentication | | `https://api.asnapieu.com` | The base URL for Airship's European cloud site when using OAuth authentication | ## Authentication {#security} ### Basic Auth (App) {#security-basicAppAuth} Type: `http` (basic) Authorization header containing the word `Basic` followed by a space and a Base64-encoded string generated from your App Key and App Secret in `appKey:appSecret` format. For example, `Basic YXBwX2tleTphcHBfc2VjcmV0`. ### Basic Auth (Master) {#security-basicAuth} Type: `http` (basic) Authorization header containing the word `Basic` followed by a space and a Base64-encoded string generated from your App Key and Master Secret in `appKey:masterSecret` format. For example, `Basic YXBwX2tleTptYXN0ZXJfc2VjcmV0`. ### Basic Auth (OAuth) {#security-basicOauth} Type: `http` (basic) Authorization header containing the word `Basic` followed by a space and a Base64-encoded string generated from your OAuth Client ID and Client Secret in `client_id:client_secret` format. For example, `Basic YXBwX2tleTptYXN0ZXJfc2VjcmV0`. Used only for requesting OAuth tokens. See [OAuth](/docs/developer/rest-api/ua/operations/oauth/). ### Bearer Token {#security-bearerAuth} Type: `http` (bearer) Authorization header containing the word `Bearer` followed by a space and a bearer token generated from the Airship dashboard. You can generate tokens for different roles. If your role does not grant you access to a feature, the endpoint will respond with a 401 status code. Tokens can be revoked at will. ### OAuth 2.0 {#security-oauth2Token} Type: `oauth2` Authorization header containing the word `Bearer` followed by a space and an OAuth 2.0 JWT bearer token provided by our authorization server. See [OAuth](/docs/developer/rest-api/ua/operations/oauth/). Make sure your requests are using the appropriate [domain in the base URL](/docs/developer/rest-api/ua/introduction/#servers). | Scope | Description | |-------|-------------| | `att` | Attachments | | `chn` | Channels | | `cnt` | Contacts | | `evt` | Events | | `lst` | Lists | | `nu` | Named Users | | `pln` | Pipelines | | `psh` | Push | | `rmc` | Remote Config | | `sch` | Schedules | | `tpl` | Content | # Airship API Authorization Reference > Find which authentication methods are supported for each Airship API endpoint. For information about each authentication method, see [Airship API Security](https://www.airship.com/docs/guides/getting-started/developers/api-security/). ## Authorization per authentication method The following table indicates supported authentication methods per endpoint in the [Airship API](https://www.airship.com/docs/developer/rest-api/ua/operations/). See the column for each authentication method to understand what access it allows. For OAuth 2.0, it lists the scope that allows access to the endpoint. | Operation | Endpoint | Public | Basic Auth (App) | Basic Auth (Master) | Bearer Token | OAuth 2.0 | | --- | --- | :---: | :---: | :---: | :---: | :---: | | [Create experiment (A/B Test)](https://www.airship.com/docs/developer/rest-api/ua/operations/a-b-tests/#createexperiment) | `POST` /api/experiments | | | | | | | [Delete experiment](https://www.airship.com/docs/developer/rest-api/ua/operations/a-b-tests/#deleteexperiment) | `DELETE` /api/experiments/scheduled/{experiment_id} | | | | | | | [Experiment listing](https://www.airship.com/docs/developer/rest-api/ua/operations/a-b-tests/#getexperiments) | `GET` /api/experiments | | | | | | | [Experiment lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/a-b-tests/#getexperiment) | `GET` /api/experiments/{experiment_id} | | | | | | | [Scheduled experiment listing](https://www.airship.com/docs/developer/rest-api/ua/operations/a-b-tests/#getscheduledexperiments) | `GET` /api/experiments/scheduled | | | | | | | [Validate experiment](https://www.airship.com/docs/developer/rest-api/ua/operations/a-b-tests/#validateexperiment) | `POST` /api/experiments/validate | | | | | | | [Create Attributes list](https://www.airship.com/docs/developer/rest-api/ua/operations/attribute-lists/#createattributelist) | `POST` /api/attribute-lists | | | | | [Lists](#lists) | | [Download list errors](https://www.airship.com/docs/developer/rest-api/ua/operations/attribute-lists/#getattributelisterrors) | `GET` /api/attribute-lists/{list_name}/errors | | | | | [Lists](#lists) | | [Retrieve lists](https://www.airship.com/docs/developer/rest-api/ua/operations/attribute-lists/#getattributelistmetadata) | `GET` /api/attribute-lists | | | | | [Lists](#lists) | | [Upload Attribute list](https://www.airship.com/docs/developer/rest-api/ua/operations/attribute-lists/#uploadattributelist) | `PUT` /api/attribute-lists/{list_name}/csv | | | | | [Lists](#lists) | | [Create pipeline (automated message)](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#createpipeline) | `POST` /api/pipelines | | | | | [Pipelines](#pipelines) | | [Delete pipeline](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#deletepipeline) | `DELETE` /api/pipelines/{pipeline_id} | | | | | [Pipelines](#pipelines) | | [Individual pipeline lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getpipeline) | `GET` /api/pipelines/{pipeline_id} | | | | | [Pipelines](#pipelines) | | [List deleted pipelines](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getdeletedpipelines) | `GET` /api/pipelines/deleted | | | | | [Pipelines](#pipelines) | | [List existing pipelines](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getpipelines) | `GET` /api/pipelines | | | | | [Pipelines](#pipelines) | | [List filtered pipelines](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getfilteredpipelines) | `GET` /api/pipelines/filtered | | | | | [Pipelines](#pipelines) | | [List pipelines constraints](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getpipelinesconstraints) | `GET` /api/pipelines/constraints | | | | | [Pipelines](#pipelines) | | [List pipelines limits](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getpipelineslimits) | `GET` /api/pipelines/limits | | | | | [Pipelines](#pipelines) | | [Update pipeline](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#updatepipeline) | `PUT` /api/pipelines/{pipeline_id} | | | | | [Pipelines](#pipelines) | | [Update pipelines constraints](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#updatepipelineconstraints) | `PUT` /api/pipelines/constraints | | | | | [Pipelines](#pipelines) | | [Validate pipeline](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#validatepipeline) | `POST` /api/pipelines/validate | | | | | [Pipelines](#pipelines) | | [Create and Send a message](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#createandsend) | `POST` /api/create-and-send | | | | | [Push](#push) | | [Create bulk send audience](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) | `POST` /api/bulk/{platform_name} | | | | | | | [Schedule a Create and Send message](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#schedulecreateandsendoperations) | `POST` /api/schedules/create-and-send | | | | | [Push](#push) | | [Schedule message with bulk ID](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#schedulebulksendpush) | `POST` /api/schedules/bulk-send | | | | | [Push](#push) | | [Send message with bulk ID](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#bulksendpush) | `POST` /api/bulk-send | | | | | [Push](#push) | | [Validate Create and Send payload](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#validatecreateandsendpayload) | `POST` /api/create-and-send/validate | | | | | [Push](#push) | | [Validate message with bulk ID](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#validatebulksendpush) | `POST` /api/bulk-send/validate | | | | | [Push](#push) | | [Channel listing](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#getchannels) | `GET` /api/channels | | | | | [Channels](#channels) | | [Channel lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#getchannel) | `GET` /api/channels/{channel_id} | | | | | [Channels](#channels) | | [Channel tags](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#modifychanneltags) | `POST` /api/channels/tags | | | | | [Channels](#channels) | | [Set or remove attributes on channels](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#modifychannelattributes) | `POST` /api/channels/attributes | | | | | [Channels](#channels) | | [Subscribe or unsubscribe channels to/from subscription lists](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#modifychannelsubscriptions) | `POST` /api/channels/subscription_lists | | | | | [Channels](#channels) | | [Uninstall channels](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#uninstallchannels) | `POST` /api/channels/uninstall | | | | | [Channels](#channels) | | [Contact association](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#associatecontact) | `POST` /api/contacts/associate | | | | | [Contacts](#contacts) | | [Contact disassociation](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#disassociatecontact) | `POST` /api/contacts/disassociate/{contact_id} | | | | | [Contacts](#contacts) | | [Contacts tags](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#modifycontacttags) | `POST` /api/contacts/tags/ | | | | | [Contacts](#contacts) | | [Look up Contact ID by Channel ID](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#getcontactidfromchannelid) | `GET` /api/contacts/lookup/channel/{channel_id} | | | | | [Contacts](#contacts) | | [Look up Contact ID by Named User ID](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#getcontactidfromnameduserid) | `GET` /api/contacts/lookup/named_user/{named_user_id} | | | | | [Contacts](#contacts) | | [Scoped Contact batch operations](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#performscopedcontactbatchoperations) | `POST` /api/contacts/scoped/{contact_id} | | | | | [Contacts](#contacts) | | [Set or remove attributes on a Contact](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#modifycontactattributes) | `POST` /api/contacts/attributes | | | | | [Contacts](#contacts) | | [Create content template](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#createcontenttemplate) | `POST` /api/content/templates | | | | | [Content](#content) | | [Create or update content template by external ID](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#updatecontenttemplatebyexternalid) | `PUT` /api/content/templates/external/{type}/{external_id} | | | | | [Content](#content) | | [Delete content template](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#deletecontenttemplate) | `DELETE` /api/content/templates/{template_id} | | | | | [Content](#content) | | [Delete content template by external ID](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#deletecontenttemplatebyexternalid) | `DELETE` /api/content/templates/external/{type}/{external_id} | | | | | [Content](#content) | | [List content templates](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#listcontenttemplates) | `GET` /api/content/templates | | | | | [Content](#content) | | [Look up a content template](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#getcontenttemplate) | `GET` /api/content/templates/{template_id} | | | | | [Content](#content) | | [Look up a content template by external ID](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#getcontenttemplatebyexternalid) | `GET` /api/content/templates/external/{type}/{external_id} | | | | | [Content](#content) | | [Update content template](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#updatecontenttemplate) | `PUT` /api/content/templates/{template_id} | | | | | [Content](#content) | | [Add Custom Events](https://www.airship.com/docs/developer/rest-api/ua/operations/custom-events/#addcustomevents) | `POST` /api/custom-events | | | | | [Events](#events) | | [Named Users uninstall](https://www.airship.com/docs/developer/rest-api/ua/operations/data-privacy-laws-compliance/#uninstallnameduser) | `POST` /api/named_users/uninstall | | | | | [Named Users](#named-users) | | [Uninstall channels](https://www.airship.com/docs/developer/rest-api/ua/operations/data-privacy-laws-compliance/#uninstallchannels) | `POST` /api/channels/uninstall | | | | | [Channels](#channels) | | [Create email attachment](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#createemailattachment) | `POST` /api/attachments | | | | | [Attachments](#attachments) | | [Custom unsubscribe email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#customunsubscribeemailchannel) | `GET` /api/channels/email/custom-unsubscribe | | | | | | | [Email tags](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#modifyemailchanneltags) | `POST` /api/channels/email/tags | | | | | [Channels](#channels) | | [Look up an email address](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#getemailchannel) | `GET` /api/channels/email/{email} | | | | | [Channels](#channels) | | [Register email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#registeremailchannel) | `POST` /api/channels/email | | | | | [Channels](#channels) | | [Remove suppression from an email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#unsuppressemailchannel) | `POST` /api/channels/email/unsuppress | | | | | [Channels](#channels) | | [Replace email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#replaceemailchannel) | `POST` /api/channels/email/replace/{channel_id} | | | | | [Channels](#channels) | | [Suppress an email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#suppressemailchannel) | `POST` /api/channels/email/suppress | | | | | [Channels](#channels) | | [Uninstall email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#uninstallemailchannel) | `POST` /api/channels/email/uninstall | | | | | [Channels](#channels) | | [Update an email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#updateemailchannel) | `PUT` /api/channels/email/{email} | | | | | [Channels](#channels) | | [Named User listing or lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#getnameduser) | `GET` /api/named_users | | | | | [Named Users](#named-users) | | [Named User update](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#updatenameduser) | `POST` /api/named_users/{named_user_id} | | | | | [Named Users](#named-users) | | [Named Users association](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#associatenameduser) | `POST` /api/named_users/associate | | | | | [Named Users](#named-users) | | [Named Users disassociation](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#disassociatednameduser) | `POST` /api/named_users/disassociate | | | | | [Named Users](#named-users) | | [Named Users tags](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#modifynamedusertags) | `POST` /api/named_users/tags | | | | | [Named Users](#named-users) | | [Named Users uninstall](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#uninstallnameduser) | `POST` /api/named_users/uninstall | | | | | [Named Users](#named-users) | | [Scoped Named User batch operations](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#performnameduserscopedbatchoperations) | `POST` /api/named_users/scoped/{named_user_id} | | | | | [Named Users](#named-users) | | [Set or remove attributes on Named Users](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#modifynameduserattributes) | `POST` /api/named_users/{named_user_id}/attributes | | | | | [Named Users](#named-users) | | [Verify public key](https://www.airship.com/docs/developer/rest-api/ua/operations/oauth/#getkeyverification) | `GET` /verify/public_key/{kid} | | | | | | | [Open channel tags](https://www.airship.com/docs/developer/rest-api/ua/operations/open-channels/#modifyopenchanneltags) | `POST` /api/channels/open/tags | | | | | [Channels](#channels) | | [Register new or update channel](https://www.airship.com/docs/developer/rest-api/ua/operations/open-channels/#createorupdateopenchannel) | `POST` /api/channels/open | | | | | [Channels](#channels) | | [Uninstall open channels](https://www.airship.com/docs/developer/rest-api/ua/operations/open-channels/#uninstallopenchannels) | `POST` /api/channels/open/uninstall | | | | | [Channels](#channels) | | [Create template](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#createtemplate) | `POST` /api/templates | | | | | | | [Delete template](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#deletetemplate) | `DELETE` /api/templates/{template_id} | | | | | | | [List templates](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#gettemplates) | `GET` /api/templates | | | | | | | [Look up a template](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#gettemplate) | `GET` /api/templates/{template_id} | | | | | | | [Push to template](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#pushtotemplate) | `POST` /api/templates/push | | | | | [Push](#push) | | [Schedule a templated push](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#scheduletemplatedpush) | `POST` /api/templates/schedules | | | | | [Push](#push) | | [Update template](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#updatetemplate) | `POST` /api/templates/{template_id} | | | | | | | [Validate a template](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#validatetemplate) | `POST` /api/templates/push/validate | | | | | [Push](#push) | | [Delete message from inbox](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#deletemessage) | `DELETE` /api/user/messages/{push_id} | | | | | | | [Delete multiple messages from inbox](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#batchdeletemessages) | `POST` /api/user/messages/batch-delete | | | | | | | [Send a push](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#sendpush) | `POST` /api/push | | | | | [Push](#push) | | [Validate a push](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#validatepush) | `POST` /api/push/validate | | | | | [Push](#push) | | [Region listing](https://www.airship.com/docs/developer/rest-api/ua/operations/regions/#getregions) | `GET` /api/regions | | | | | | | [Region lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/regions/#getregion) | `GET` /api/regions/{region_id} | | | | | | | [Activity log report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getactivitylogreport) | `GET` /api/reports/activity/details | | | | | | | [App opens report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getappopensreport) | `GET` /api/reports/opens | | | | | | | [Custom Events detail listing](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getcustomeventsreport) | `GET` /api/reports/events | | | | | | | [Custom Events per group summary](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getcustomeventspergroupsummary) | `GET` /api/reports/events/summary/pergroup/{group_id} | | | | | | | [Custom Events per push summary](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getcustomeventsperpushsummary) | `GET` /api/reports/events/summary/perpush/{push_id} | | | | | | | [Devices report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getdevicesreport) | `GET` /api/reports/devices | | | | | | | [Experiment overview report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getexperimentoverviewreport) | `GET` /api/reports/experiment/overview/{push_id} | | | | | | | [Experiment variant report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getexperimentvariantreport) | `GET` /api/reports/experiment/detail/{push_id}/{variant_id} | | | | | | | [Individual push response statistics](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getresponsesforpush) | `GET` /api/reports/responses/{push_id} | | | | | | | [Opt-in report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getoptinreport) | `GET` /api/reports/optins | | | | | | | [Opt-out report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getoptoutreport) | `GET` /api/reports/optouts | | | | | | | [Per group push detail report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getpergrouppushdetailreport) | `GET` /api/reports/pergroup/detail/{group_id} | | | | | | | [Per group push time series report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getpergrouppushtimeseriesreport) | `GET` /api/reports/pergroup/series/{group_id} | | | | | | | [Per push detail report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getperpushdetailreport) | `GET` /api/reports/perpush/detail/{push_id} | | | | | | | [Per push time series report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getperpushtimeseriesreport) | `GET` /api/reports/perpush/series/{push_id} | | | | | | | [Push body per push](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getpushbodyperpush) | `GET` /api/reports/perpush/pushbody/{push_id} | | | | | | | [Push report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getpushreport) | `GET` /api/reports/sends | | | | | | | [Response listing](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getresponses) | `GET` /api/reports/responses/list | | | | | | | [Response report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getresponsereport) | `GET` /api/reports/responses | | | | | | | [Time in app report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#gettimeinappreport) | `GET` /api/reports/timeinapp | | | | | | | [Web response report](https://www.airship.com/docs/developer/rest-api/ua/operations/reports/#getwebresponsereport) | `GET` /api/reports/web/interaction | | | | | | | [Delete schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#deleteschedule) | `DELETE` /api/schedules/{schedule_id} | | | | | [Schedules](#schedules) | | [List a specific schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#getschedule) | `GET` /api/schedules/{schedule_id} | | | | | [Schedules](#schedules) | | [List schedules](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#getschedules) | `GET` /api/schedules | | | | | [Schedules](#schedules) | | [Pause a schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#pauseschedule) | `POST` /api/schedules/{schedule_id}/pause | | | | | [Schedules](#schedules) | | [Resume a schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#resumeschedule) | `POST` /api/schedules/{schedule_id}/resume | | | | | [Schedules](#schedules) | | [Schedule a notification](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#schedulenotification) | `POST` /api/schedules | | | | | [Push](#push) | | [Update schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#updateschedule) | `PUT` /api/schedules/{schedule_id} | | | | | [Schedules](#schedules) | | [Create Segment](https://www.airship.com/docs/developer/rest-api/ua/operations/segments/#createsegment) | `POST` /api/segments | | | | | | | [Delete Segment](https://www.airship.com/docs/developer/rest-api/ua/operations/segments/#deletesegment) | `DELETE` /api/segments/{segment_id} | | | | | | | [Segment listing](https://www.airship.com/docs/developer/rest-api/ua/operations/segments/#getsegments) | `GET` /api/segments | | | | | | | [Segment lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/segments/#getsegment) | `GET` /api/segments/{segment_id} | | | | | | | [Update Segment](https://www.airship.com/docs/developer/rest-api/ua/operations/segments/#updatesegment) | `PUT` /api/segments/{segment_id} | | | | | | | [Custom SMS response](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#createcustomsmsresponse) | `POST` /api/sms/custom-response | | | | | | | [Manually trigger a keyword interaction](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#triggersmskeywordinteraction) | `POST` /api/sms/{msisdn}/keywords | | | | | | | [Opt-out of SMS messages](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#optoutsmschannel) | `POST` /api/channels/sms/opt-out | | | | | [Channels](#channels) | | [Register SMS channel](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#registersmschannel) | `POST` /api/channels/sms | | | | | [Channels](#channels) | | [SMS channel lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#getsmschannel) | `GET` /api/channels/sms/{msisdn}/{sender} | | | | | [Channels](#channels) | | [SMS tags](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#modifysmschanneltags) | `POST` /api/channels/sms/tags | | | | | [Channels](#channels) | | [Uninstall SMS channel](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#uninstallsmschannel) | `POST` /api/channels/sms/uninstall | | | | | [Channels](#channels) | | [Update SMS channel](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#updatesmschannel) | `PUT` /api/channels/sms/{channel_id} | | | | | [Channels](#channels) | | [Create list](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#createstaticlist) | `POST` /api/lists | | | | | [Lists](#lists) | | [Delete a list](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#deletestaticlist) | `DELETE` /api/lists/{list_name} | | | | | [Lists](#lists) | | [Download a list of channels](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#getstaticlist) | `GET` /api/lists/{list_name}/csv | | | | | [Lists](#lists) | | [Get single list metadata](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#getstaticlistmetadata) | `GET` /api/lists/{list_name} | | | | | [Lists](#lists) | | [Retrieve lists](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#getstaticlistsmetadata) | `GET` /api/lists | | | | | [Lists](#lists) | | [Update list contents](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#updatestaticlist) | `PUT` /api/lists/{list_name}/csv | | | | | [Lists](#lists) | | [Update list metadata](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#updatestaticlistmetadata) | `PUT` /api/lists/{list_name} | | | | | [Lists](#lists) | | [Named User subscription lists listing](https://www.airship.com/docs/developer/rest-api/ua/operations/subscription-lists/#getnamedusersubscriptionlists) | `GET` /api/subscription_lists/named_users/{named_user_id} | | | | | [Named Users](#named-users) | | [Subscription lists listing](https://www.airship.com/docs/developer/rest-api/ua/operations/subscription-lists/#getsubscriptionlists) | `GET` /api/subscription_lists | | | | | [Lists](#lists) | | [Create a tag list](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#createtaglist) | `POST` /api/tag-lists | | | | | [Lists](#lists) | | [Delete tag list](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#deletetaglist) | `DELETE` /api/tag-lists/{list_name} | | | | | [Lists](#lists) | | [Download list errors](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#gettaglisterrors) | `GET` /api/tag-lists/{list_name}/errors | | | | | [Lists](#lists) | | [Retrieve lists](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#gettaglistsmetadata) | `GET` /api/tag-lists | | | | | [Lists](#lists) | | [Upload tag list](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#uploadtaglist) | `PUT` /api/tag-lists/{list_name}/csv | | | | | [Lists](#lists) | | [Channel tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifychanneltags) | `POST` /api/channels/tags | | | | | [Channels](#channels) | | [Contacts tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifycontacttags) | `POST` /api/contacts/tags/ | | | | | [Contacts](#contacts) | | [Email tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifyemailchanneltags) | `POST` /api/channels/email/tags | | | | | [Channels](#channels) | | [Named Users tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifynamedusertags) | `POST` /api/named_users/tags | | | | | [Named Users](#named-users) | | [Open channel tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifyopenchanneltags) | `POST` /api/channels/open/tags | | | | | [Channels](#channels) | | [SMS tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifysmschanneltags) | `POST` /api/channels/sms/tags | | | | | [Channels](#channels) | {class="table-col-2-wrap"} ## OAuth token scopes Refer to the following sections when setting permissions for [OAuth client credentials](https://www.airship.com/docs/guides/getting-started/developers/api-security/#oauth-20). ### Attachments The Attachments (`att`) scope includes endpoints that manage attachments for messages and templates. | Operation | Endpoint | | --- | --- | | [Create email attachment](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#createemailattachment) | `POST` /api/attachments | {class="table-col-1-40 table-col-2-wrap"} ### Channels The Channels (`chn`) scope includes endpoints that manage channels and channel data. | Operation | Endpoint | | --- | --- | | [Channel listing](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#getchannels) | `GET` /api/channels | | [Channel lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#getchannel) | `GET` /api/channels/{channel_id} | | [Channel tags](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#modifychanneltags) | `POST` /api/channels/tags | | [Set or remove attributes on channels](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#modifychannelattributes) | `POST` /api/channels/attributes | | [Subscribe or unsubscribe channels to/from subscription lists](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#modifychannelsubscriptions) | `POST` /api/channels/subscription_lists | | [Uninstall channels](https://www.airship.com/docs/developer/rest-api/ua/operations/channels/#uninstallchannels) | `POST` /api/channels/uninstall | | [Uninstall channels](https://www.airship.com/docs/developer/rest-api/ua/operations/data-privacy-laws-compliance/#uninstallchannels) | `POST` /api/channels/uninstall | | [Email tags](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#modifyemailchanneltags) | `POST` /api/channels/email/tags | | [Look up an email address](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#getemailchannel) | `GET` /api/channels/email/{email} | | [Register email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#registeremailchannel) | `POST` /api/channels/email | | [Remove suppression from an email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#unsuppressemailchannel) | `POST` /api/channels/email/unsuppress | | [Replace email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#replaceemailchannel) | `POST` /api/channels/email/replace/{channel_id} | | [Suppress an email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#suppressemailchannel) | `POST` /api/channels/email/suppress | | [Uninstall email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#uninstallemailchannel) | `POST` /api/channels/email/uninstall | | [Update an email channel](https://www.airship.com/docs/developer/rest-api/ua/operations/email/#updateemailchannel) | `PUT` /api/channels/email/{email} | | [Open channel tags](https://www.airship.com/docs/developer/rest-api/ua/operations/open-channels/#modifyopenchanneltags) | `POST` /api/channels/open/tags | | [Register new or update channel](https://www.airship.com/docs/developer/rest-api/ua/operations/open-channels/#createorupdateopenchannel) | `POST` /api/channels/open | | [Uninstall open channels](https://www.airship.com/docs/developer/rest-api/ua/operations/open-channels/#uninstallopenchannels) | `POST` /api/channels/open/uninstall | | [Opt-out of SMS messages](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#optoutsmschannel) | `POST` /api/channels/sms/opt-out | | [Register SMS channel](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#registersmschannel) | `POST` /api/channels/sms | | [SMS channel lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#getsmschannel) | `GET` /api/channels/sms/{msisdn}/{sender} | | [SMS tags](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#modifysmschanneltags) | `POST` /api/channels/sms/tags | | [Uninstall SMS channel](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#uninstallsmschannel) | `POST` /api/channels/sms/uninstall | | [Update SMS channel](https://www.airship.com/docs/developer/rest-api/ua/operations/sms/#updatesmschannel) | `PUT` /api/channels/sms/{channel_id} | | [Channel tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifychanneltags) | `POST` /api/channels/tags | | [Email tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifyemailchanneltags) | `POST` /api/channels/email/tags | | [Open channel tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifyopenchanneltags) | `POST` /api/channels/open/tags | | [SMS tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifysmschanneltags) | `POST` /api/channels/sms/tags | {class="table-col-1-40 table-col-2-wrap"} ### Contacts The Contacts (`cnt`) scope includes endpoints that manage contacts and contact lists. | Operation | Endpoint | | --- | --- | | [Contact association](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#associatecontact) | `POST` /api/contacts/associate | | [Contact disassociation](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#disassociatecontact) | `POST` /api/contacts/disassociate/{contact_id} | | [Contacts tags](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#modifycontacttags) | `POST` /api/contacts/tags/ | | [Look up Contact ID by Channel ID](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#getcontactidfromchannelid) | `GET` /api/contacts/lookup/channel/{channel_id} | | [Look up Contact ID by Named User ID](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#getcontactidfromnameduserid) | `GET` /api/contacts/lookup/named_user/{named_user_id} | | [Scoped Contact batch operations](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#performscopedcontactbatchoperations) | `POST` /api/contacts/scoped/{contact_id} | | [Set or remove attributes on a Contact](https://www.airship.com/docs/developer/rest-api/ua/operations/contacts/#modifycontactattributes) | `POST` /api/contacts/attributes | | [Contacts tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifycontacttags) | `POST` /api/contacts/tags/ | {class="table-col-1-40 table-col-2-wrap"} ### Events The Events (`evt`) scope includes endpoints that create custom events. | Operation | Endpoint | | --- | --- | | [Add Custom Events](https://www.airship.com/docs/developer/rest-api/ua/operations/custom-events/#addcustomevents) | `POST` /api/custom-events | {class="table-col-1-40 table-col-2-wrap"} ### Lists The Lists (`lst`) scope includes endpoints that manage lists and list uploads. | Operation | Endpoint | | --- | --- | | [Create Attributes list](https://www.airship.com/docs/developer/rest-api/ua/operations/attribute-lists/#createattributelist) | `POST` /api/attribute-lists | | [Download list errors](https://www.airship.com/docs/developer/rest-api/ua/operations/attribute-lists/#getattributelisterrors) | `GET` /api/attribute-lists/{list_name}/errors | | [Retrieve lists](https://www.airship.com/docs/developer/rest-api/ua/operations/attribute-lists/#getattributelistmetadata) | `GET` /api/attribute-lists | | [Upload Attribute list](https://www.airship.com/docs/developer/rest-api/ua/operations/attribute-lists/#uploadattributelist) | `PUT` /api/attribute-lists/{list_name}/csv | | [Create list](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#createstaticlist) | `POST` /api/lists | | [Delete a list](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#deletestaticlist) | `DELETE` /api/lists/{list_name} | | [Download a list of channels](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#getstaticlist) | `GET` /api/lists/{list_name}/csv | | [Get single list metadata](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#getstaticlistmetadata) | `GET` /api/lists/{list_name} | | [Retrieve lists](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#getstaticlistsmetadata) | `GET` /api/lists | | [Update list contents](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#updatestaticlist) | `PUT` /api/lists/{list_name}/csv | | [Update list metadata](https://www.airship.com/docs/developer/rest-api/ua/operations/static-lists/#updatestaticlistmetadata) | `PUT` /api/lists/{list_name} | | [Subscription lists listing](https://www.airship.com/docs/developer/rest-api/ua/operations/subscription-lists/#getsubscriptionlists) | `GET` /api/subscription_lists | | [Create a tag list](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#createtaglist) | `POST` /api/tag-lists | | [Delete tag list](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#deletetaglist) | `DELETE` /api/tag-lists/{list_name} | | [Download list errors](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#gettaglisterrors) | `GET` /api/tag-lists/{list_name}/errors | | [Retrieve lists](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#gettaglistsmetadata) | `GET` /api/tag-lists | | [Upload tag list](https://www.airship.com/docs/developer/rest-api/ua/operations/tag-lists/#uploadtaglist) | `PUT` /api/tag-lists/{list_name}/csv | {class="table-col-1-40 table-col-2-wrap"} ### Named Users The Named Users (`nu`) scope includes endpoints that manage named users and named user associations. | Operation | Endpoint | | --- | --- | | [Named Users uninstall](https://www.airship.com/docs/developer/rest-api/ua/operations/data-privacy-laws-compliance/#uninstallnameduser) | `POST` /api/named_users/uninstall | | [Named User listing or lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#getnameduser) | `GET` /api/named_users | | [Named User update](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#updatenameduser) | `POST` /api/named_users/{named_user_id} | | [Named Users association](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#associatenameduser) | `POST` /api/named_users/associate | | [Named Users disassociation](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#disassociatednameduser) | `POST` /api/named_users/disassociate | | [Named Users tags](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#modifynamedusertags) | `POST` /api/named_users/tags | | [Named Users uninstall](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#uninstallnameduser) | `POST` /api/named_users/uninstall | | [Scoped Named User batch operations](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#performnameduserscopedbatchoperations) | `POST` /api/named_users/scoped/{named_user_id} | | [Set or remove attributes on Named Users](https://www.airship.com/docs/developer/rest-api/ua/operations/named-users/#modifynameduserattributes) | `POST` /api/named_users/{named_user_id}/attributes | | [Named User subscription lists listing](https://www.airship.com/docs/developer/rest-api/ua/operations/subscription-lists/#getnamedusersubscriptionlists) | `GET` /api/subscription_lists/named_users/{named_user_id} | | [Named Users tags](https://www.airship.com/docs/developer/rest-api/ua/operations/tags/#modifynamedusertags) | `POST` /api/named_users/tags | {class="table-col-1-40 table-col-2-wrap"} ### Pipelines The Pipelines (`pln`) scope includes endpoints that manage automated message pipelines. | Operation | Endpoint | | --- | --- | | [Create pipeline (automated message)](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#createpipeline) | `POST` /api/pipelines | | [Delete pipeline](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#deletepipeline) | `DELETE` /api/pipelines/{pipeline_id} | | [Individual pipeline lookup](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getpipeline) | `GET` /api/pipelines/{pipeline_id} | | [List deleted pipelines](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getdeletedpipelines) | `GET` /api/pipelines/deleted | | [List existing pipelines](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getpipelines) | `GET` /api/pipelines | | [List filtered pipelines](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getfilteredpipelines) | `GET` /api/pipelines/filtered | | [List pipelines constraints](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getpipelinesconstraints) | `GET` /api/pipelines/constraints | | [List pipelines limits](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#getpipelineslimits) | `GET` /api/pipelines/limits | | [Update pipeline](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#updatepipeline) | `PUT` /api/pipelines/{pipeline_id} | | [Update pipelines constraints](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#updatepipelineconstraints) | `PUT` /api/pipelines/constraints | | [Validate pipeline](https://www.airship.com/docs/developer/rest-api/ua/operations/automation/#validatepipeline) | `POST` /api/pipelines/validate | {class="table-col-1-40 table-col-2-wrap"} ### Push The Push (`psh`) scope includes endpoints that send push notifications and scheduled messages. | Operation | Endpoint | | --- | --- | | [Create and Send a message](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#createandsend) | `POST` /api/create-and-send | | [Schedule a Create and Send message](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#schedulecreateandsendoperations) | `POST` /api/schedules/create-and-send | | [Schedule message with bulk ID](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#schedulebulksendpush) | `POST` /api/schedules/bulk-send | | [Send message with bulk ID](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#bulksendpush) | `POST` /api/bulk-send | | [Validate Create and Send payload](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#validatecreateandsendpayload) | `POST` /api/create-and-send/validate | | [Validate message with bulk ID](https://www.airship.com/docs/developer/rest-api/ua/operations/bulk-sending/#validatebulksendpush) | `POST` /api/bulk-send/validate | | [Push to template](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#pushtotemplate) | `POST` /api/templates/push | | [Schedule a templated push](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#scheduletemplatedpush) | `POST` /api/templates/schedules | | [Validate a template](https://www.airship.com/docs/developer/rest-api/ua/operations/personalization/#validatetemplate) | `POST` /api/templates/push/validate | | [Send a push](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#sendpush) | `POST` /api/push | | [Validate a push](https://www.airship.com/docs/developer/rest-api/ua/operations/push/#validatepush) | `POST` /api/push/validate | | [Schedule a notification](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#schedulenotification) | `POST` /api/schedules | {class="table-col-1-40 table-col-2-wrap"} ### Schedules The Schedules (`sch`) scope includes endpoints that manage scheduled messages. | Operation | Endpoint | | --- | --- | | [Delete schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#deleteschedule) | `DELETE` /api/schedules/{schedule_id} | | [List a specific schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#getschedule) | `GET` /api/schedules/{schedule_id} | | [List schedules](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#getschedules) | `GET` /api/schedules | | [Pause a schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#pauseschedule) | `POST` /api/schedules/{schedule_id}/pause | | [Resume a schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#resumeschedule) | `POST` /api/schedules/{schedule_id}/resume | | [Update schedule](https://www.airship.com/docs/developer/rest-api/ua/operations/schedules/#updateschedule) | `PUT` /api/schedules/{schedule_id} | {class="table-col-1-40 table-col-2-wrap"} ### Content The Content (`tpl`) scope includes endpoints that manage content templates. | Operation | Endpoint | | --- | --- | | [Create content template](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#createcontenttemplate) | `POST` /api/content/templates | | [Create or update content template by external ID](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#updatecontenttemplatebyexternalid) | `PUT` /api/content/templates/external/{type}/{external_id} | | [Delete content template](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#deletecontenttemplate) | `DELETE` /api/content/templates/{template_id} | | [Delete content template by external ID](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#deletecontenttemplatebyexternalid) | `DELETE` /api/content/templates/external/{type}/{external_id} | | [List content templates](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#listcontenttemplates) | `GET` /api/content/templates | | [Look up a content template](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#getcontenttemplate) | `GET` /api/content/templates/{template_id} | | [Look up a content template by external ID](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#getcontenttemplatebyexternalid) | `GET` /api/content/templates/external/{type}/{external_id} | | [Update content template](https://www.airship.com/docs/developer/rest-api/ua/operations/content/#updatecontenttemplate) | `PUT` /api/content/templates/{template_id} | {class="table-col-1-40 table-col-2-wrap"} #### Operations API endpoints organized by functionality. Each section groups related operations for managing different aspects of the platform. # A/B Tests > Create A/B Tests using the `/api/experiments` endpoint. An experiment or A/B test is a set of distinct push notification variants sent to subsets of an audience. You can create up to 26 notification variants and send each variant to an audience subset. {{< important >}} The A/B Tests API is unrelated to the [current version of A/B testing](/docs/guides/experimentation/a-b-tests/messages/). For more information about this API, including its dashboard equivalent, see [Legacy message A/B tests](/docs/guides/experimentation/a-b-tests/messages-legacy/). {{< /important >}} ## Create experiment (A/B Test) {#createexperiment} Create an experiment. The body of the request should consist of a single experiment object. The experiment is processed and sent immediately unless a schedule is present. [Jump to examples ↓](#createexperiment-examples) ### `POST /api/experiments` {{< important >}} The A/B Tests API is unrelated to the [current version of A/B testing](/docs/guides/experimentation/a-b-tests/messages/). For more information about this API, including its dashboard equivalent, see [Legacy message A/B tests](/docs/guides/experimentation/a-b-tests/messages-legacy/). {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Request body** **Content-Type:** `application/json` [Experiment object]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#experimentobject) **Responses** **`201`** The experiment was created. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The newly created experiment. | Response body: **Content-Type:** `application/json` - **`experiment_id`** `string` Unique identifier for an experiment. Format: `uuid` Example: `0f7704e9-5dc0-4f7d-9964-e89055701b0a` - **`ok`** `boolean` **REQUIRED** If true, the experiment was successfully created. If false, the experiment was not created. - **`operation_id`** `string` A unique string that represents a single API call, used to identify the operation or side effects in reporting and troubleshooting logs. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`push_id`** `string` Unique identifier for a push. Format: `uuid` Example: `7e13f060-594c-11e4-8ed6-0800200c9a66` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/experiments HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name": "Experiment 1", "audience": {"tag": "earlyBirds"}, "device_types": [ "ios", "android" ], "variants": [ { "push": { "notification": { "alert": "message 1" } } }, { "push": { "notification": { "alert": "message 2" } } } ] } ``` ```http HTTP/1.1 201 Created Content-Length: 123 Location: https://go.urbanairship.com/api/experiments/0f7704e9-5dc0-4f7d-9964-e89055701b0a Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : "true", "operation_id" : "03ca94a3-2b27-42f6-be7e-41efc2612cd4", "experiment_id" : "0f7704e9-5dc0-4f7d-9964-e89055701b0a", "push_id" : "7e13f060-594c-11e4-8ed6-0800200c9a66" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Schedule schedule = Schedule.newBuilder() .setScheduledTimestamp(DateTime.now().plusMinutes(5)) .build(); Variant variantOne = Variant.newBuilder() .setPushPayload(VariantPushPayload.newBuilder() .setNotification(Notification.newBuilder() .setAlert("message 1") .build() ) .build()) .setSchedule(schedule) .build(); Variant variantTwo = Variant.newBuilder() .setPushPayload(VariantPushPayload.newBuilder() .setNotification(Notification.newBuilder() .setAlert("message 2") .build() ) .build()) .setSchedule(schedule) .build(); Experiment experiment = Experiment.newBuilder() .setName("Experiment 1") .setDescription("Testing description") .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID)) .setAudience(Selectors.tag("earlyBirds")) .addVariant(variantOne) .addVariant(variantTwo) .build(); ExperimentRequest request = ExperimentRequest.newRequest(experiment); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, ABTest, Experiment, Variant ) from urbanairship.push import notification client = BasicAuthClient( key='', secret='' ) # Create push notifications for variants push_1 = notification(alert='message 1') push_2 = notification(alert='message 2') # Create variants variants = [ Variant(push=push_1), Variant(push=push_2) ] # Create experiment experiment = Experiment( audience={'tag': 'earlyBirds'}, device_types=['ios', 'android'], variants=variants, name='Experiment 1' ) # Create and send experiment ab_test = ABTest(airship=client) response = ab_test.create(experiment=experiment) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') variant_one = UA::Variant.new(client: airship) variant_one.push = { "notification": { "alert": "message 1" } } variant_two = UA::Variant.new(client: airship) variant_two.push = { "notification": { "alert": "message 2" } } experiment = UA::Experiment.new(client: airship) experiment.name = 'Experiment 1' experiment.description = 'Example experiment' experiment.audience = UA.tag('earlyBirds') experiment.device_types = ['ios','android'] experiment.variants << variant_one.payload experiment.variants << variant_two.payload ab_test = UA::AbTest.new(client: airship) ab_test.experiment_object = experiment.payload ab_test.create_ab_test ``` --- ## Delete experiment {#deleteexperiment} Delete a scheduled experiment. You can only delete experiments before they start; attempting to delete an experiment that has already started or completed will return an HTTP 405 response ("Method not allowed"). [Jump to examples ↓](#deleteexperiment-examples) ### `DELETE /api/experiments/scheduled/{experiment_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `experiment_id` | `string` | Required | The unique identifier of the experiment. | **Responses** **`200`** Returned if the experiment has been successfully deleted. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` **REQUIRED** Success. - **`operation_id`** `string` A unique string that represents a single API call, used to identify the operation or side effects in reporting and troubleshooting logs. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`405`** Returned when a request is made using an HTTP method not supported by the endpoint. For example, sending a DELETE to /api/schedules. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http DELETE /api/experiments/scheduled/0f7704e9-5dc0-4f7d-9964-e89055701b0a HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Length: 123 Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : "true", "operation_id" : "03ca94a3-2b27-42f6-be7e-41efc2612cd4" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ExperimentDeleteRequest request = ExperimentDeleteRequest.newRequest("0f7704e9-5dc0-4f7d-9964-e89055701b0a"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, ABTest ) client = BasicAuthClient( key='', secret='' ) ab_test = ua.ABTest(client) ab_test.experiment_id = "0f7704e9-5dc0-4f7d-9964-e89055701b0a" response = ab_test.delete() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') ab_test = UA::AbTest.new(client: airship) ab_test.experiment_id = '0f7704e9-5dc0-4f7d-9964-e89055701b0a' ab_test.delete_ab_test ``` --- ## Experiment listing {#getexperiments} List experiments, sorted by `created_at` [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) from newest to oldest. Responses are paginated. Use optional `limit` and `offset` parameters to navigate results. [Jump to examples ↓](#getexperiments-examples) ### `GET /api/experiments` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `limit` | `integer` | | Positive maximum number of elements to return per page. The default `limit` is 10 entries with a maximum of 100 entries. Min: 1 Max: 100 | | `offset` | `integer` | | A zero-based integer offset into the result set. If you do not use an offset, results will begin with the most recently sent experiment. If `offset` is greater than the number of queryable experiments, an empty result will be returned. | **Responses** **`200`** Returned on success, with the JSON representation of the experiments in the body of the response. Response body: **Content-Type:** `application/json` - **`count`** `integer` The number of items returned in this page of results. - **`experiments`** `array` <[Experiment object]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#experimentobject)> Experiment objects sorted by either `created_at` from newest to oldest. The number of objects will never exceed the limit specified in the request. - **`next_page`** `string` A relative URL leading to the next page of results. If there are no more results, next_page is absent. - **`ok`** `boolean` **REQUIRED** If true, the call was successful. - **`total_count`** `integer` The total number of results. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/experiments HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Length: 123 Data-Attribute: experiments Count: 2 Total-Count: 2 Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : "true", "count" : 2, "total_count" : 2, "experiments" : [{ "name" : "Experiment 1", "control" : 0.33, "audience" : "all", "device_types": [ "ios", "android" ], "variants" : [{ "push" : { "notification" : { "alert" : "message 1" } }, "id" : 0, }, { "push" : { "notification" : { "alert" : "message 2" } }, "id" : 1, }], "id" : "b5bc3dd1-9ea4-4208-b5f1-9e7ac3fe0502", "created_at" : "2020-03-03T21:08:05", "push_id" : "07cec298-6b8c-49f9-8e03-0448a06f4aac" }, { "name" : "Experiment 2", "description" : "The second experiment", "audience" : "all", "device_types": [ "ios", "android" ], "variants" : [{ "push" : { "notification" : { "alert" : "message 1" } }, "id" : 0, }, { "push" : { "notification" : { "alert" : "message 2" } }, "id" : 1, }], "id" : "e464aa7e-be40-4994-a290-1bbada7187d8", "created_at" : "2020-03-03T21:08:05", "push_id" : "07cec298-6b8c-49f9-8e03-0448a06f4aac" }] } ``` ```python from urbanairship import ( BasicAuthClient, ABTest ) client = BasicAuthClient( key='', secret='' ) ab_test = ABTest(airship=client) response = ab_test.list_experiments() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') ab_test = UA::AbTest.new(client: airship) ab_test.limit = 5 ab_test.list_ab_test ``` --- ## Experiment lookup {#getexperiment} Look up an experiment (A/B Test). [Jump to examples ↓](#getexperiment-examples) ### `GET /api/experiments/{experiment_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `experiment_id` | `string` | Required | The ID of the experiment you want to look up. | **Responses** **`200`** Returned on success, with the JSON representation of the experiment in the body of the response. Response body: **Content-Type:** `application/json` - **`experiment`** `object` <[Experiment object]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#experimentobject)> An experiment object describes an A/B test, including the audience and variant portions. - **`ok`** `boolean` **REQUIRED** If true, the operation completed successfully and returns a result set. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/experiments/0f7704e9-5dc0-4f7d-9964-e89055701b0a HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Length: 123 Data-Attribute: experiment Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : "true", "experiment" : { "id" : "0f7704e9-5dc0-4f7d-9964-e89055701b0a", "push_id": "d00f07b0-594c-11e4-8ed6-0800200c9a66", "name" : "Experiment 1", "audience" : "all", "device_types": [ "ios", "android" ], "variants" : [{ "push" : { "notification" : { "alert" : "message 1" } }, "id" : 0, }, { "push" : { "notification" : { "alert" : "message 2" } }, "id" : 1, }] } } ``` ```python from urbanairship import BasicAuthClient, ABTest client = BasicAuthClient( key='', secret='' ) ab_test = ABTest(client) response = ab_test.lookup(experiment_id='0f7704e9-5dc0-4f7d-9964-e89055701b0a') ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') ab_test = UA::AbTest.new(client: airship) ab_test.experiment_id = '0f7704e9-5dc0-4f7d-9964-e89055701b0a' ab_test.lookup_ab_test ``` --- ## Scheduled experiment listing {#getscheduledexperiments} List scheduled experiments in order, from closest to the current [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) to farthest (i.e., the experiments scheduled to occur soonest will appear at the top of the list). Responses are paginated, using optional `limit` and `offset` parameters. [Jump to examples ↓](#getscheduledexperiments-examples) ### `GET /api/experiments/scheduled` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `limit` | `integer` | | Positive maximum number of elements to return per page. The default `limit` is 10 entries with a maximum of 100 entries. Min: 1 Max: 100 | | `offset` | `integer` | | A zero-based integer offset into the result set. If you do not use an offset, results will begin with experiment scheduled to begin at the soonest [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format). If the `offset` is greater than the number of queryable experiments, the result set will be empty. | **Responses** **`200`** Returned on success, with the JSON representation of the experiments in the body of the response. Response body: **Content-Type:** `application/json` - **`count`** `integer` The number of items in this page of results. - **`experiments`** `array` <[Experiment object]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#experimentobject)> Experiments listed by `scheduled_time` in ascending time order. The number of objects will never exceed the `limit` specified in the request. - **`next_page`** `string` A relative URL leading to the next page of results. If there are no more results, next_page is absent. - **`ok`** `boolean` **REQUIRED** If true, the operation completed successfully and returns an expected result set. - **`total_count`** `integer` The total number of results. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/experiments/scheduled HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Length: 123 Data-Attribute: experiments Content-Type: application/vnd.urbanairship+json; version=3 { "ok": "true", "count": 2, "total_count": 2, "experiments": [ { "id": "0f7704e9-5dc0-4f7d-9964-e89055701b0a", "name": "Experiment 1", "audience": "all", "device_types": [ "ios", "android" ], "variants": [ { "id": 0, "schedule": { "scheduled_time": "2020-11-17T20:58:00Z" }, "push": { "notification": { "alert": "message 1" } } }, { "id": 1, "schedule": { "scheduled_time": "2020-11-17T20:58:00Z" }, "push": { "notification": { "alert": "message 2" } } } ] }, { "id": "29705c10-5951-11e4-8ed6-0800200c9a66", "name": "Experiment 2", "audience": "all", "device_types": [ "ios", "android" ], "variants": [ { "id": 0, "schedule": { "scheduled_time": "2020-12-17T20:58:00Z" }, "push": { "notification": { "alert": "message 1" } } }, { "id": 1, "schedule": { "scheduled_time": "2020-12-17T20:58:00Z" }, "push": { "notification": { "alert": "message 2" } } } ] } ] } ``` ```python from urbanairship import ( BasicAuthClient, ABTest ) client = BasicAuthClient( key='', secret='' ) ab_test = ABTest(client) response = ab_test.list_scheduled_experiment() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') ab_test = UA::AbTest.new(client: airship) ab_test.list_scheduled_ab_test ``` --- ## Validate experiment {#validateexperiment} Accepts the same range of payloads as `/api/experiments`, but only parses and validates the payload without creating the experiment. This does the same amount of validation as the creation endpoint, including platform-specific validation, e.g., APNs byte limit checks. While this operation ensures the experiment is technically valid, it does not guarantee that a resulting push will succeed. An experiment may validate and still fail to be delivered. For example, you may have a valid experiment with no devices in your audience. [Jump to examples ↓](#validateexperiment-examples) ### `POST /api/experiments/validate` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Request body** A single experiment object. **Content-Type:** `application/json` [Experiment object]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#experimentobject) **Responses** **`200`** The experiment is valid. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` **REQUIRED** If true, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string that represents a single API call, used to identify the operation or side effects in reporting and troubleshooting logs. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/experiments/validate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name": "Experiment 1", "audience": {"tag": "earlyBirds"}, "device_types": [ "ios", "android" ], "variants": [ { "push": { "notification": { "alert": "message 1" } } }, { "push": { "notification": { "alert": "message 2" } } } ] } ``` ```http HTTP/1.1 200 OK Content-Length: 123 Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : "true", "operation_id" : "03ca94a3-2b27-42f6-be7e-41efc2612cd4" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Schedule schedule = Schedule.newBuilder() .setScheduledTimestamp(DateTime.now().plusMinutes(5)) .build(); Variant variantOne = Variant.newBuilder() .setPushPayload(VariantPushPayload.newBuilder() .setNotification(Notification.newBuilder() .setAlert("message 1") .build() ) .build()) .setSchedule(schedule) .build(); Variant variantTwo = Variant.newBuilder() .setPushPayload(VariantPushPayload.newBuilder() .setNotification(Notification.newBuilder() .setAlert("message 2") .build() ) .build()) .setSchedule(schedule) .build(); Experiment experiment = Experiment.newBuilder() .setName("Experiment 1") .setDescription("Testing description") .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID)) .setAudience(Selectors.tag("earlyBirds")) .addVariant(variantOne) .addVariant(variantTwo) .build(); ExperimentRequest request = ExperimentRequest.newRequest(experiment).setValidateOnly(true); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, ABTest, Experiment, Variant ) from urbanairship.push import notification client = BasicAuthClient( key='', secret='' ) # Create push notifications for variants push_1 = notification(alert='message 1') push_2 = notification(alert='message 2') # Create variants variants = [ Variant(push=push_1), Variant(push=push_2) ] # Create experiment experiment = Experiment( audience={'tag': 'earlyBirds'}, device_types=['ios', 'android'], variants=variants, name='Experiment 1' ) # Validate experiment ab_test = ABTest(airship=client) response = ab_test.validate(experiment=experiment) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') variant_one = UA::Variant.new(client: airship) variant_one.push = { "notification": { "alert": "message 1" } } variant_two = UA::Variant.new(client: airship) variant_two.push = { "notification": { "alert": "message 2" } } experiment = UA::Experiment.new(client: airship) experiment.name = 'Experiment 1' experiment.description = 'Example experiment' experiment.audience = UA.tag('earlyBirds') experiment.device_types = ['ios','android'] experiment.variants << variant_one.payload experiment.variants << variant_two.payload ab_test = UA::AbTest.new(client: airship) ab_test.experiment_object = experiment.payload ab_test.validate_ab_test ``` --- # Attribute Lists > Define and manage attribute lists; upload corresponding attribute data in CSV format. ## Create Attributes list {#createattributelist} Create a new Attributes list by defining it in the Airship system. The body of the request contains the name, description, and optional metadata for the list. After you define a list, you populate it with a call to the [Upload Attribute List](/docs/developer/rest-api/ua/operations/attribute-lists/#uploadattributelist) endpoint. [Jump to examples ↓](#createattributelist-examples) ### `POST /api/attribute-lists` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Request body** **Content-Type:** `application/json` - **`description`** `string` An optional description for the list. Min length: 1, Max length: 1000 - **`extra`** `object` An optional JSON map of up to 100 key-value (string-to-string) pairs associated with the list. Keys in this object have a 64-character maximum; values can be up to 1,024 characters. - **`name`** `string` **REQUIRED** The name of the list, consists of up to 64 URL-safe characters. The name is how the list is identified, so it should be unique and memorable. Note: Since the `name` portion of the URL may represent any Unicode string, it must be encoded properly as a URI path component. The `encodeURIComponent` function in JavaScript can be used. The list name must include a prefix that determines how empty values are handled: - Lists with `ua_attributes_` prefix: Empty or null values are ignored, preserving any existing attribute values not explicitly set in the CSV. This mode is useful for making partial updates to a user's attributes without affecting others. - Lists with `ua_attributes_snapshot_` prefix: Empty or null values trigger removing those attributes from the user. This mode is useful for synchronizing attribute states with external systems, ensuring the attributes in the CSV exactly match the user's attributes. Min length: 1, Max length: 64 **Responses** **`201`** The list was created successfully. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The URI of the list, used for later updates. | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`409`** The request conflicts with another request. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/attribute-lists HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name": "ua_attributes_my_new_list", "description": "First of many attributes lists!", "extra": { "filename": "attributes.csv", "source": "CRM" } } ``` ```http HTTP/1.1 201 Created Content-Type: application/json Location: https://go.urbanairship.com/api/attribute-lists/ua_attributes_my_new_list { "ok" : true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); AttributeListsCreateRequest attributeListsCreateRequest = AttributeListsCreateRequest.newRequest("ua_attributes_list") .setDescription("ua_attributes_list") .addExtra("filename", "attributes.csv") .addExtra("source","crm"); Response response = client.execute(attributeListsCreateRequest); ``` ```python from urbanairship import ( BasicAuthClient, AttributeList ) client = BasicAuthClient( key='', secret='' ) attribute_list = AttributeList( client=client, list_name="ua_attributes_my_new_list", description="First of many attributes lists!", extra={ "filename": "attributes.csv", "source": "CRM" } ) attribute_list.create() ``` --- ## Download list errors {#getattributelisterrors} During processing, after a list is uploaded, errors can occur. Depending on the type of list processing, an error file may be created, showing a user exactly what went wrong. [Jump to examples ↓](#getattributelisterrors-examples) ### `GET /api/attribute-lists/{list_name}/errors` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The name of the list. | **Responses** **`200`** The response will contain the errors found during list processing. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [List response object]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#listobject) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/attribute-lists/ua_attributes_list/errors HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+csv; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: text/csv 8b4de669-16f1-4e71-9a1f-0c62a8235a65,ERROR,"Unable to parse number: forty-two" d5ebe607-a3e6-4601-b97e-83ec604223fe,ERROR,"Unable to parse date: monday" ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); AttributeListsErrorsRequest attributeListsErrorsRequest = AttributeListsErrorsRequest.newRequest("ua_attributes_list"); Response response = client.execute(attributeListsErrorsRequest); ``` ```python from urbanairship import ( BasicAuthClient, AttributeList ) client = BasicAuthClient( key='', secret='' ) attribute_list = AttributeList( client=client, list_name="ua_attributes_list", description="example list", ) errors = attribute_list.get_errors() ``` --- ## Retrieve lists {#getattributelistmetadata} Retrieve information about all Attributes lists. This call returns a list of metadata that will not contain the actual lists of users. [Jump to examples ↓](#getattributelistmetadata-examples) ### `GET /api/attribute-lists` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Responses** **`200`** Lists metadata retrieved successfully. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`lists`** `array` <[List response object]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#listobject)> An array of list objects. - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/attribute-lists HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: lists Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "lists": [ { "name": "ua_attributes_my_list", "description": "My first list", "extra": { "filename": "list.csv", "source": "crm" }, "created": "2020-05-13T21:41:25", "last_updated": "2020-05-13T21:45:17", "channel_count": 0, "error_path": "https://go.urbanairship.com/api/attribute-lists/ua_attributes_my_list/errors", "status": "ready" }, { "name": "ua_attributes_another_list", "description": "My second list", "extra": { "filename": "list2.csv", "source": "api" }, "created": "2020-05-14T21:41:25", "last_updated": "2020-05-14T21:45:17", "channel_count": 0, "error_path": "https://go.urbanairship.com/api/attribute-lists/ua_attributes_another_list/errors", "status": "ready" } ] } ``` ```python from urbanairship import ( BasicAuthClient, AttributeList ) client = BasicAuthClient( key='', secret='' ) listing = AttributeList.list(airship=client) listing.json() ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); AttributeListsListingRequest attributeListsListingRequest = AttributeListsListingRequest.newRequest(); Response response = client.execute(attributeListsListingRequest); ``` --- ## Upload Attribute list {#uploadattributelist} Upload a CSV that will set Attribute values on the specified channels or Named Users. CSV guidelines: - The first entry in the uploaded CSV must be a header row. The first field must be one of the following identifier types: `channel_id`, `msisdn`, `email_address`, or `named_user`. - Only one identifier type is allowed per file unless the identifier type name matches a custom Attribute schema for the associated app key. - You must include both `msisdn` and `sms_sender` columns when targeting SMS or MMS channel types. See example to the right. - Uploads must be newline-delimited identifiers (text/CSV) as described in RFC 4180, with commas as the delimiter, optionally double-quoted values, UTF-8 encoded, and with CRLF or LF line separators. Required column headers per identifier type: | Target type | Required column headers | |------------------|------------------------------------------------------------------------------------------| | iOS | `channel_id` | | Android | `channel_id` | | Named User | `named_user` | | Web | `channel_id` | | Email | `email_address` | | Open Channel | `channel_id` | | SMS |
  • `msisdn` (numeric and no leading 0)
  • `sms_sender` (numeric, e.g., `1234`)
| | MMS |
  • `msisdn` (numeric and no leading 0)
  • `sms_sender` (numeric, e.g., `1234`)
| Optional Fields: Opt-in dates can optionally be set for new channels when the identifier is an `email_address` or `msisdn`. | Target type | Optional column headers | |-----------------|------------------------------------------------------------------------------------------| | SMS | `ua_opted_in` (UTC Timestamp) | | MMS | `ua_opted_in` (UTC Timestamp) | | Email |
  • `ua_transactional_opted_in` (UTC Timestamp)
  • `ua_commercial_opted_in` (UTC Timestamp)
| [Jump to examples ↓](#uploadattributelist-examples) ### `PUT /api/attribute-lists/{list_name}/csv` {{< note >}} A list can contain a maximum of 10 million rows and 101 columns: one identifier column and 100 Attribute or internal header columns. `Content-Encoding: gzip` is supported and recommended on this endpoint to reduce network traffic. {{< /note >}} {{< warning >}} If your upload times out due to a poor connection, you must re-upload the list from scratch. Because we want to ensure that the entirety of a given list is successfully uploaded, we do not support partial list uploads. {{< /warning >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The `name` of the list you want to upload. | **Request body** **Content-Type:** `text/csv` Type: `string` **Responses** **`202`** The request has been accepted for processing. Response body: **Content-Type:** `application/json` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** Bad Request. Parsing or validating the request failed. | Error code | Description | |---|---| | 40002 | CSV contains too many identifiers | | 40003 | CSV header contains too many columns | | 40013 | CSV header's first field must be an identifier | | 40014 | CSV header contains an unknown Attribute name | | 40015 | CSV header contains duplicate Attribute names | | 40017 | CSV header contains duplicate column names | | 40018 | CSV header does not contain required column for identifier type | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Upload Attribute list example* ```http PUT /api/attribute-lists/ua_attributes_list/csv HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv channel_id,Magic Score,Preferred Sport c543f3a3-bc1d-4830-8dee-7532c6a23b9a,100,Basketball 6ba360a0-1f73-4ee7-861e-95f6c1ed6410,,Basketball 15410d17-687c-46fa-bbd9-f255741a1523,2,Football c2c64ef7-8f5c-470e-915f-f5e3da04e1df,22.1,Rugby ``` *Upload Attribute Snapshot list example* ```http PUT /api/attribute-lists/ua_attributes_snapshot_list/csv HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv channel_id,Magic Score,Preferred Sport,Favorite Team c543f3a3-bc1d-4830-8dee-7532c6a23b9a,100,Basketball,Lakers 6ba360a0-1f73-4ee7-861e-95f6c1ed6410,,,, 15410d17-687c-46fa-bbd9-f255741a1523,2,Football, c2c64ef7-8f5c-470e-915f-f5e3da04e1df,22.1,,Patriots # In this example using a Snapshot CSV: # - First user has all attributes set # - Second user has all attributes removed (empty values) # - Third user has Magic Score and Preferred Sport set, but Favorite Team removed # - Fourth user has Magic Score and Favorite Team set, but Preferred Sport removed ``` ```python from urbanairship import ( BasicAuthClient, AttributeList ) client = BasicAuthClient( key='', secret='' ) # For standard attribute lists, use ua_attributes_ prefix standard_list = AttributeList( client=client, list_name="ua_attributes_list", description="example standard list", ) standard_list.upload(file_path="path/to/standard_file.csv") # For attributesnapshot lists, use ua_attributes_snapshot_ prefix snapshot_list = AttributeList( client=client, list_name="ua_attributes_snapshot_list", description="example snapshot list", ) snapshot_list.upload(file_path="path/to/snapshot_file.csv") ``` *Upload Attribute list for SMS example* ```http PUT /api/attribute-lists/ua_attributes_list/csv HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv msisdn,sms_sender,firstName 5035556789,18588675309,Jane 4155551212,18588675309,Rory ``` ```http HTTP/1.1 202 Accepted Content-Type: application/json { "ok" : true } ``` ```python from urbanairship import ( BasicAuthClient, AttributeList ) client = BasicAuthClient( key='', secret='' ) attribute_list = AttributeList( client=client, list_name="ua_attributes_list", description="example list", ) attribute_list.upload(file_path="path/to/sms_file.csv") ``` --- # Automation > Manage Automated notifications using the `/api/pipelines` endpoints. {{< note >}} In the dashboard UI, we refer to pipelines as *Automation* or *Automated Messages*. {{< /note >}} ## Create pipeline (automated message) {#createpipeline} Create one or more pipelines. You can provide a single [pipeline object](/docs/developer/rest-api/ua/schemas/pipeline-objects/#pipelineobject) or an array of [pipeline objects](/docs/developer/rest-api/ua/schemas/pipeline-objects/#pipelineobject). [Jump to examples ↓](#createpipeline-examples) ### `POST /api/pipelines` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Request body** A single [pipeline object](/docs/developer/rest-api/ua/schemas/pipeline-objects/#pipelineobject) or an array of pipeline objects. **Content-Type:** `application/json` **One of:** - [Pipeline object]({{< ref "/developer/rest-api/ua/schemas/pipeline-objects/" >}}#pipelineobject) A pipeline object encapsulates the complete set of objects that define an Automation pipeline: Triggers, Outcomes, and metadata. At least one of `immediate_trigger` or `historical_trigger` must be supplied. - `array` **Responses** **`201`** If creating more than one pipeline, pipeline URIs are returned in the same order as the pipeline objects in the request. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying a single API call. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`pipeline_urls`** `array[string]` An array of of pipeline URIs. If more than one entity was included in the request, the URIs will be in the same order as the objects in the request. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`409`** The request conflicts with another request. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/pipelines HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name":"The Darkest Pipeline", "enabled":true, "immediate_trigger":"first_open", "outcome":{ "push":{ "audience":"triggered", "device_types":[ "ios", "android", "web" ], "notification":{ "alert":"Cool goatee, Abed" } } }, "timing":{ "delay":{ "seconds":7200 }, "schedule":{ "type":"local", "miss_behavior":"wait", "dayparts":[ { "days_of_week":[ "thursday" ], "allowed_times":[ { "preferred":"21:30:00" } ] } ] } } } ``` ```http HTTP/1.1 201 Created Content-Length: 123 Data-Attribute: pipeline_urls Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "86ad9239-373d-d0a5-d5d8-04fed18f79bc", "pipeline_urls": [ "https://go.urbanairship/api/pipelines/86ad9239-373d-d0a5-d5d8-04fed18f79bc" ] } ``` ```python from urbanairship import ( BasicAuthClient, Automation ) from urbanairship.automation.pipeline import Pipeline client = BasicAuthClient( key='', secret='' ) automation = Automation(client) pipeline = Pipeline( name='The Darkest Pipeline', enabled=True, immediate_trigger='first_open', outcome={ 'push': { 'audience': 'triggered', 'device_types': ['ios', 'android', 'web'], 'notification': {'alert': 'Cool goatee, Abed'} } }, timing={ 'delay': {'seconds': 7200}, 'schedule': { 'type': 'local', 'miss_behavior': 'wait', 'dayparts': [{ 'days_of_week': ['thursday'], 'allowed_times': [ {'preferred': '21:30:00'} ] }] } } ) response = automation.create(pipeline.payload) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') pipeline = UA::Pipeline.new(client: airship) pipeline.enabled = true pipeline.immediate_trigger = "first_open" pipeline.outcome = { "push": { "audience": "triggered", "device_types": ['ios','android','web'], "notification": { "alert": "Cool goatee, Abed" } } } automation = UA::Automation.new(client: airship) automation.pipeline_object = pipeline.payload details = automation.create_automation puts(details) ``` --- ## Delete pipeline {#deletepipeline} Delete a pipeline. [Jump to examples ↓](#deletepipeline-examples) ### `DELETE /api/pipelines/{pipeline_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `pipeline_id` | `string` | Required | The pipeline you want to return or modify. | **Responses** **`204`** An API request was successful, but there is no response body to return. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http DELETE /api/pipelines/0f927674-918c-31ef-51ca-e96fdd234da4 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 204 No Content ``` ```python from urbanairship import ( BasicAuthClient, Automation ) from urbanairship.automation.pipeline import Pipeline client = BasicAuthClient( key='', secret='' ) automation = Automation(client) response = automation.delete('0f927674-918c-31ef-51ca-e96fdd234da4') ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') automation = UA::Automation.new(client: airship) automation.pipeline_id = '0f927674-918c-31ef-51ca-e96fdd234da4' automation.delete_automation ``` --- ## Individual pipeline lookup {#getpipeline} Fetch a single pipeline resource. Returns an array containing a single pipeline object in the `pipeline` attribute. [Jump to examples ↓](#getpipeline-examples) ### `GET /api/pipelines/{pipeline_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `pipeline_id` | `string` | Required | The pipeline you want to return or modify. | **Responses** **`200`** Returned on success, with the JSON representation of the pipeline in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`next_page`** `string` An URI that points to the next page of pipelines. The page size is specified by the `limit` parameter and the start point by the `start` parameter. If there are no more pipelines for a next page we omit the next page link. - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying a single API call. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`pipeline_ids`** `array[string]` An array of pipeline IDs. - **`pipeline_urls`** `array[string]` An array of of pipeline URIs. If more than one entity was included in the request, the URIs will be in the same order as the objects in the request. - **`pipelines`** `array` <[Pipeline object]({{< ref "/developer/rest-api/ua/schemas/pipeline-objects/" >}}#pipelineobject)> A list of pipeline objects. - **`prev_page`** `string` An URI that points to the previous page of pipelines. The page size is specified by the `limit` parameter and the start point by the `start` parameter. If there are no more pipelines for a previous page we omit the previous page link. - **`total_count`** `integer` The total count of pipelines. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/pipelines/4d3ff1fd-9ce6-5ea4-5dc9-5ccbd38597f4 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "pipeline": { "creation_time": "2020-02-14T19:19:19", "enabled": true, "immediate_trigger": { "tag_added": "new_customer" }, "last_modified_time": "2020-03-01T12:12:54", "name": "New customer", "outcome": { "push": { "audience": "triggered", "device_types": [ "ios", "android" ], "notification": { "alert": "Hello new customer!" } } }, "status": "live", "uid": "86ad9239-373d-d0a5-d5d8-04fed18f79bc", "url": "https://go.urbanairship/api/pipelines/86ad9239-373d-d0a5-d5d8-04fed18f79bc" } } ``` ```python from urbanairship import ( BasicAuthClient, Automation ) from urbanairship.automation.pipeline import Pipeline client = BasicAuthClient( key='', secret='' ) automation = Automation(client) pipeline = automation.lookup('4d3ff1fd-9ce6-5ea4-5dc9-5ccbd38597f4') ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') automation = UA::Automation.new(client: airship) automation.pipeline_id = '4d3ff1fd-9ce6-5ea4-5dc9-5ccbd38597f4' automation.lookup_automation ``` --- ## List deleted pipelines {#getdeletedpipelines} Produces a list of all deleted pipelines starting with the most recently deleted entry. [Jump to examples ↓](#getdeletedpipelines-examples) ### `GET /api/pipelines/deleted` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | | The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) of the starting element for paginating results. | | `limit` | `integer` | | The maximum number of elements to return. | **Responses** **`200`** Returns an array of deleted pipeline objects. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` Success. - **`pipelines`** `array[object]` **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/pipelines/deleted/ HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "pipelines": [ { "deletion_time": "2020-03-31T20:54:45", "pipeline_id": "0sdicj23-fasc-4b2f-zxcv-0baf934f0d69" }, { "..." } ] } ``` ```python from urbanairship import ( BasicAuthClient, Automation ) from urbanairship.automation.pipeline import Pipeline client = BasicAuthClient( key='', secret='' ) automation = Automation(client) response = automation.list_deleted_automations() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') automation = UA::Automation.new(client: airship) automation.start = 2020-11-23 automation.list_deleted_automations ``` --- ## List existing pipelines {#getpipelines} List existing pipelines. Pipelines are ordered by `creation_date` from newest to oldest. [Jump to examples ↓](#getpipelines-examples) ### `GET /api/pipelines` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `limit` | `integer` | | The maximum number of results to return. This is effectively the page size for the response. No default limit. For maximum performance, set your limit between 25 and 100. Min: 1 | | `enabled` | `boolean` | | If true, limits the listing to enabled pipelines (`"enabled": true`). If false or omitted, lists all pipelines, whether `enabled` is `true` or `false`. | | `offset` | `integer` | | The first result you want to return. This parameter assists in pagination. | **Responses** **`200`** Returned on success, with a JSON representation of pipelines matching your query parameters. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`next_page`** `string` An URI that points to the next page of pipelines. The page size is specified by the `limit` parameter and the start point by the `start` parameter. If there are no more pipelines for a next page we omit the next page link. - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying a single API call. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`pipeline_ids`** `array[string]` An array of pipeline IDs. - **`pipeline_urls`** `array[string]` An array of of pipeline URIs. If more than one entity was included in the request, the URIs will be in the same order as the objects in the request. - **`pipelines`** `array` <[Pipeline object]({{< ref "/developer/rest-api/ua/schemas/pipeline-objects/" >}}#pipelineobject)> A list of pipeline objects. - **`prev_page`** `string` An URI that points to the previous page of pipelines. The page size is specified by the `limit` parameter and the start point by the `start` parameter. If there are no more pipelines for a previous page we omit the previous page link. - **`total_count`** `integer` The total count of pipelines. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/pipelines/ HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "pipelines": [ { "creation_time": "2020-03-20T18:37:23", "enabled": true, "immediate_trigger": { "tag_added": { "tag": "bought_shoes" } }, "last_modified_time": "2020-03-20T19:35:12", "name": "Shoe buyers", "outcome": { "push": { "audience": "triggered", "device_types": [ "android" ], "notification": { "alert": "So you like shoes, huh?" } } }, "status": "live", "uid": "3987f98s-89s3-cx98-8z89-89adjkl29zds", "url": "https://go.urbanairship.com/api/pipelines/3987f98s-89s3-cx98-8z89-89adjkl29zds" }, { "..." } ] } ``` ```python from urbanairship import ( BasicAuthClient, Automation ) from urbanairship.automation.pipeline import Pipeline client = BasicAuthClient( key='', secret='' ) automation = Automation(client) for pipeline in automation.list_automations(): print(pipeline) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') automation = UA::Automation.new(client: airship) automation.limit = 5 automation.list_automations ``` --- ## List filtered pipelines {#getfilteredpipelines} Lists all pipelines, which fulfill the provided filter criteria. Returns a response container, which contains an array of pipeline objects in the `pipelines` attribute. The response container also provides total count and links to the next page `next_page` and previous page `prev_page`, if applicable. We also always apply a sort order. By default we apply an ascending sort order on the name `name` field, but we also support a sort order on the started date `started_date` field. Pagination is always applied, which means that the pipeline result list is not the complete list of pipelines if the total count is greater than the page limit. ### `GET /api/pipelines/filtered` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `integer` | | Non-negative zero-based index of the starting element for paginating results. Default value 0. Min: 1 | | `limit` | `integer` | | The maximum number of results to return. This is effectively the page size for the response. Min: 1 | | `enabled` | `boolean` | | If true, limits the listing to enabled pipelines. If false or omitted, lists all pipelines, whether `enabled` is `true` or `false`. | | `started_date_mills` | `integer` | | Limits the listing to only pipelines that were started after the specified date in milliseconds. | | `prefix` | `string` | | Search term, which is used as a prefix search term. | | `triggers` | `string` | | 0 or more trigger types. The triggers filter limits the listing of pipelines by the specified trigger types. For example, if you specify `REGION_EXITED` and `REGION_ENTERED`, only pipelines that are associated with region entry and region exit triggers will be shown. If no trigger types are specified, no triggers filter will be applied and all pipelines will be listed. Possible values: `TAG_ADDED`, `TAG_REMOVED`, `FIRST_REG`, `FIRST_OPT_IN`, `ACTIVITY`, `REGION_ENTERED`, `REGION_EXITED`, `CUSTOM_EVENT`, `SUBSCRIPTION_ADDED`, `SUBSCRIPTION_REMOVED` | | `sort` | `string` | | Specifies the field, which should be sorted. Two fields are supported: `name` and `started_date`. If you omit the `sort` parameter, the default value `name` is used. If you provide an unknown field name, we will default to the `name` field. Possible values: `name`, `started_date` | | `order` | `string` | | Specifies the sort order as ascending (`asc`) or descending (`desc`). If you omit the `order` parameter, the default value `asc` is used. Possible values: `asc`, `desc` | **Responses** **`200`** Returned on success, with a JSON representation of pipelines matching your query parameters. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`next_page`** `string` An URI that points to the next page of pipelines. The page size is specified by the `limit` parameter and the start point by the `start` parameter. If there are no more pipelines for a next page we omit the next page link. - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying a single API call. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`pipeline_ids`** `array[string]` An array of pipeline IDs. - **`pipeline_urls`** `array[string]` An array of of pipeline URIs. If more than one entity was included in the request, the URIs will be in the same order as the objects in the request. - **`pipelines`** `array` <[Pipeline object]({{< ref "/developer/rest-api/ua/schemas/pipeline-objects/" >}}#pipelineobject)> A list of pipeline objects. - **`prev_page`** `string` An URI that points to the previous page of pipelines. The page size is specified by the `limit` parameter and the start point by the `start` parameter. If there are no more pipelines for a previous page we omit the previous page link. - **`total_count`** `integer` The total count of pipelines. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) --- ## List pipelines constraints {#getpipelinesconstraints} Returns an array of cross-pipeline rate limit constraints. These are the rates that the combination of all pipelines for an app may not exceed. [Jump to examples ↓](#getpipelinesconstraints-examples) ### `GET /api/pipelines/constraints` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Responses** **`200`** Returns an array of cross-pipeline rate limit constraints. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`constraints`** `array[object]` An array of rate objects determining the maximum number of messages each audience member can receive over a period of time. - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/pipelines/constraints/ HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "constraints" : [ { "rate" : { "pushes" : 30, "lifetimes" : 1 } }, { "rate" : { "pushes" : 15, "days" : 3 } }, { "rate" : { "pushes" : 4, "hours" : 6 } } ] } ``` --- ## List pipelines limits {#getpipelineslimits} Return the currently configured limits for number of total and active pipelines, as well as the total and active counts. [Jump to examples ↓](#getpipelineslimits-examples) ### `GET /api/pipelines/limits` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Responses** **`200`** Returns a JSON dictionary in the `limits` attribute. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`limits`** `object` **OBJECT PROPERTIES** - **`active_count`** `integer` An integer indicating the number of pipelines created by the application which are currently enabled. - **`active_limit`** `integer` An integer indicating the total number of active pipelines that the app is allowed to have. - **`total_count`** `integer` An integer indicating the total number of pipelines that currently exist for the application, regardless of their enabled state. - **`total_limit`** `integer` An integer indicating the total number of pipelines that the app is allowed to have, regardless of their enabled state. - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/pipelines/limits/ HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "limits" : { "total_limit" : 50, "active_limit" : 20, "total_count" : 23, "active_count" : 7 } } ``` --- ## Update pipeline {#updatepipeline} Update the state of a single pipeline resource. You must include the complete payload from a POST response, with changes you want to make to the resource. You cannot provide a partial payload. If you omit optional fields during this operation that were already set for the pipeline, they will be nullified. [Jump to examples ↓](#updatepipeline-examples) ### `PUT /api/pipelines/{pipeline_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `pipeline_id` | `string` | Required | The pipeline you want to return or modify. | **Request body** A single pipeline object or an array of pipeline objects. **Content-Type:** `application/json` [Pipeline object]({{< ref "/developer/rest-api/ua/schemas/pipeline-objects/" >}}#pipelineobject) **Responses** **`200`** Returned if the pipeline has been successfully updated. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`409`** The request conflicts with another request. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http PUT /api/pipelines/0f927674-918c-31ef-51ca-e96fdd234da4 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json; { "enabled": true, "immediate_trigger": { "tag_added": "new_customer" }, "outcome": { "push": { "audience": "triggered", "device_types": [ "ios" ], "notification": { "alert": "Hello new customer!" } } } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, Automation ) from urbanairship.automation.pipeline import Pipeline client = BasicAuthClient( key='', secret='' ) automation = Automation(client) pipeline = Pipeline( enabled=True, immediate_trigger={ 'tag_added': 'new_customer' }, outcome={ 'audience': 'triggered', 'device_types': ['ios'], 'notification': notification(alert='Hello new customer!') } ) response = automation.update( pipeline_id='0f927674-918c-31ef-51ca-e96fdd234da4', pipeline=pipeline.payload ) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') pipeline = UA::Pipeline.new(client: airship) pipeline.enabled = true pipeline.immediate_trigger = { "tag_added": { "tag": "new_customer", "group": "crm" } } pipeline.outcome = { "push": { "audience": "triggered", "device_types": ["ios"], "notification": { "alert": "Hello new customer!" } } } automation = UA::Automation.new(client: airship) automation.pipeline_id = '0f927674-918c-31ef-51ca-e96fdd234da4' automation.pipeline_object = pipeline.payload automation.update_automation ``` --- ## Update pipelines constraints {#updatepipelineconstraints} Update the pipelines constraints. [Jump to examples ↓](#updatepipelineconstraints-examples) ### `PUT /api/pipelines/constraints` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Request body** An array of no more than 5 cross-pipeline rate limit constraints. **Content-Type:** `application/json` - **`constraints`** `array[object]` An array of rate objects determining the maximum number of messages each audience member can receive over a period of time. Max items: 5 - **`ok`** `boolean` Success. **Responses** **`200`** Everything worked as expected. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http PUT /api/pipelines/constraints/ HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "constraints" : [ { "rate" : { "pushes" : 15, "days" : 3 } }, { "rate" : { "pushes" : 4, "hours" : 6 } } ] } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` --- ## Validate pipeline {#validatepipeline} This endpoint accepts the same range of payloads as a `POST` to `/api/pipelines`, but only parses and validates the payload, without creating the pipeline. The body of the request must be a single pipeline object or an array of pipeline objects. [Jump to examples ↓](#validatepipeline-examples) ### `POST /api/pipelines/validate` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): pln **Request body** A single pipeline object or an array of pipeline objects. **Content-Type:** `application/json` **One of:** - [Pipeline object]({{< ref "/developer/rest-api/ua/schemas/pipeline-objects/" >}}#pipelineobject) A pipeline object encapsulates the complete set of objects that define an Automation pipeline: Triggers, Outcomes, and metadata. At least one of `immediate_trigger` or `historical_trigger` must be supplied. - `array` **Responses** **`200`** Everything worked as expected. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/pipelines/validate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name":"The Darkest Pipeline", "enabled":true, "immediate_trigger":"first_open", "outcome":{ "push":{ "audience":"triggered", "device_types":[ "ios", "android" ], "notification":{ "alert":"Cool goatee, Abed" } } }, "timing":{ "delay":{ "seconds":7200 }, "schedule":{ "type":"local", "miss_behavior":"wait", "dayparts":[ { "days_of_week":[ "thursday" ], "allowed_times":[ { "preferred":"21:30:00" } ] } ] } } } ``` ```http HTTP/1.1 200 OK Content-Length: 11 Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, Automation ) from urbanairship.automation.pipeline import Pipeline client = BasicAuthClient( key='', secret='' ) automation = Automation(client) pipeline = Pipeline( name='The Darkest Pipeline', enabled=True, immediate_trigger='first_open', outcome={ 'push': { 'audience': 'triggered', 'device_types': ['ios', 'android', 'web'], 'notification': notification(alert='Cool goatee, Abed') } }, timing={ 'delay': {'seconds': 7200}, 'schedule': { 'type': 'local', 'miss_behavior': 'wait', 'dayparts': [{ 'days_of_week': ['thursday'], 'allowed_times': [ {'preferred': '21:30:00'} ] }] } } ) response = automation.validate(pipeline.payload) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') pipeline = UA::Pipeline.new(client: airship) pipeline.enabled = true pipeline.immediate_trigger = "first_open" pipeline.outcome = { "push": { "audience": "triggered", "device_types": ['ios','android','web'], "notification": { "alert": "Cool goatee, Abed" } } } automation = UA::Automation.new(client: airship) automation.pipeline_object = pipeline.payload automation.validate_automation ``` --- # Bulk Sending > Target recipients of a single channel type by providing audience identifiers at send time. Bulk sending supports two methods: * **Upload and Send** targets existing channels by Channel ID across app, web, email, SMS, and Open channels. Upload a CSV of Channel IDs to the [Create bulk send audience](/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) endpoint to obtain a `bulk_id`, and then send your message using the [Send message with bulk ID](/developer/rest-api/ua/operations/bulk-sending/#bulksendpush) or [Schedule message with bulk ID](/developer/rest-api/ua/operations/bulk-sending/#schedulebulksendpush) endpoint. * **Create and Send** sends to email addresses, MSISDNs, or Open channel addresses. Unknown identifiers are registered as new channels. * For smaller audiences, use the [Create and Send a message](/developer/rest-api/ua/operations/bulk-sending/#createandsend) or [Schedule a Create and Send message](/developer/rest-api/ua/operations/bulk-sending/#schedulecreateandsendoperations) endpoints to provide email addresses, MSISDNs, or Open channel addresses in an array. * For larger audiences, upload identifiers in CSV format to the [Create bulk send audience](/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) endpoint to obtain a `bulk_id`, and then send your message using the [Create and Send a message](/developer/rest-api/ua/operations/bulk-sending/#createandsend) or [Schedule a Create and Send message](/developer/rest-api/ua/operations/bulk-sending/#schedulecreateandsendoperations) endpoint. See the [Bulk sending](/guides/audience/segmentation/bulk-sending/) guide for more information. ## Create and Send a message {#createandsend} Send messages to email addresses, MSISDNs, or Open channel addresses. Unknown identifiers are registered as new channels. This endpoint supports two audience methods: - `create_and_send` array: For smaller audiences, provide email addresses, MSISDNs, or Open channel addresses directly in the request. - `bulk_id`: For larger audiences, upload a CSV using the [Create bulk send audience](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) endpoint to obtain a `bulk_id`, then reference it in this request. Existing channels that are `opted_in` or have a newer `opted_in` value in the payload receive the message but are not re-registered. You cannot update `opted_in` values for existing channels through this endpoint. Note: This endpoint also accepts Channel IDs for app or web via `bulk_id`, but this works identically to [Send message with bulk ID](/docs/developer/rest-api/ua/operations/bulk-sending/#bulksendpush). [Jump to examples ↓](#createandsend-examples) ### `POST /api/create-and-send` {{< warning >}} Duplicate addresses in the `create_and_send` array might receive redundant notifications or fewer notifications than expected. You should remove duplicate addresses from your request before sending a Create and Send message. {{< /warning >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** **Content-Type:** `application/json` **One of:** - [Create and Send to email channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#email) The payload for a Create and Send operation to email channels. When sending to email channels, `device_types` must be set to `email`. - [Create and Send to SMS channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#sms) The payload for a Create and Send operation to SMS channels. When sending to SMS channels, `device_types` must be set to `sms`. - [Create and Send MMS notification]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#mms) The payload for a Create and Send operation that sends a multimedia payload (MMS) to SMS channels. When sending an MMS payload, `device_types` must be set to `mms`. - [Create and Send to open channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#open) The payload for a Create and Send operation to open channels. When sending to open channels, the `device_type` must be set to `open::`. **Responses** **`202`** Because this operation sends messages, a successful response is nearly identical to a `/api/push` response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`content_urls`** `array[string]` An array of URLs where the push payload contains a landing page action. Min items: 0, Max items: 100 - **`localized_ids`** `array[string]` An array of identifiers used for reporting. Each ID represents a localized message (push object with `localizations` array). - **`message_ids`** `array[string]` An array of message IDs, each uniquely identifying a Message Center message. - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`push_ids`** `array[string]` An array of push IDs, each uniquely identifying a push. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example Create and Send a message for email* ```http POST /api/create-and-send HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "create_and_send" : [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22", "ua_open_tracking_opted_in": "2022-11-02T10:35:00", "ua_click_tracking_opted_in": "2022-11-02T10:36:00" }, { "ua_address" : "ben@example.com", "ua_commercial_opted_in": "2020-11-29T12:45:10", "ua_open_tracking_opted_out": "2022-11-02T10:35:00", "ua_click_tracking_opted_out": "2022-11-02T10:36:00" } ] }, "device_types" : [ "email" ], "notification" : { "email": { "subject": "Welcome to the Winter Sale! ", "html_body": "

Seasons Greetings

Check out our winter deals!

Unsubscribe

", "plaintext_body": "Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]", "message_type": "commercial", "sender_name": "Airship", "sender_address": "team@airship.com", "reply_to": "no-reply@airship.com", "click_tracking": false, "open_tracking": false } }, "campaigns": { "categories": ["winter sale", "west coast"] } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); String htmlBodyString = "

Seasons Greetings

Check out our winter deals!

Unsubscribe

"; String plaintextBodyString = "Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]"; EmailChannel newChannel = EmailChannel.newBuilder() .setAddress("new@example.com") .setCommertialOptedIn(DateTime.parse("2020-11-29T10:34:22Z")) .build(); EmailChannel benChannel = EmailChannel.newBuilder() .setAddress("ben@example.com") .setTransactionalOptedIn(DateTime.parse("2020-11-29T12:45:10Z")) .build(); CreateAndSendAudience audience = new CreateAndSendAudience(EmailChannels.newBuilder() .addChannel(newChannel) .addChannel(benChannel) .build()); CreateAndSendEmailPayload createAndSendEmailPayload = CreateAndSendEmailPayload.newBuilder() .setSubject("Welcome to the Winter Sale! ") .setHtmlBody(htmlBodyString) .setPlaintextBody(plaintextBodyString) .setMessageType(MessageType.TRANSACTIONAL) .setSenderName("Airship") .setSenderAddress("team@airship.com") .setReplyTo("no-reply@airship.com") .build(); Notification notification = Notification.newBuilder() .addDeviceTypeOverride(DeviceType.EMAIL, createAndSendEmailPayload) .build(); Campaigns campaign = Campaigns.newBuilder() .addCategory("winter sale") .addCategory("west coast") .build(); CreateAndSendPayload payload = CreateAndSendPayload.newBuilder() .setAudience(audience) .setNotification(notification) .setCampaigns(campaign) .build(); CreateAndSendRequest request = CreateAndSendRequest.newRequest(payload); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, CreateAndSendPush, email, sms, mms, campaigns ) client = BasicAuthClient(key='', secret='') # Create and Send a message for email push = CreateAndSendPush(client) push.audience = { "create_and_send": [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22" }, { "ua_address": "ben@example.com", "ua_commercial_opted_out": "2020-11-29T12:45:10" }, { "ua_address": "mary@example.com", "ua_email_suppression_state": "BOUNCE" } ] } push.device_types = ["email"] push.notification = email( subject="Welcome to the Winter Sale!", html_body="

Seasons Greetings

Check out our winter deals!

Unsubscribe

", plaintext_body="Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]", message_type="transactional", sender_name="Airship", sender_address="team@airship.com", reply_to="no-reply@airship.com", click_tracking=False, open_tracking=False, attachments=[ {"id": "0e10a6b9-725c-4f6b-9af2-9ef5b31328c0"}, {"id": "5503b5fe-ed69-4609-bef6-6fef0e6e428f"} ] ) push.campaigns = campaigns(categories=["winter sale", "west coast"]) response = push.send() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_notification = UA::EmailNotification.new(client: airship) email_notification.bypass_opt_in_level = false email_notification.html_body = "

Seasons Greetings

Check out our winter deals!

Unsubscribe

" email_notification.message_type = 'transactional' email_notification.plaintext_body = 'Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]' email_notification.reply_to = 'no-reply@airship.com' email_notification.sender_address = 'team@airship.com' email_notification.sender_name = 'Airship' email_notification.subject = 'Welcome to the Winter Sale!' override = email_notification.email_override send_it = UA::CreateAndSend.new(client: airship) send_it.addresses = [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22" }, { "ua_address": "ben@example.com", "ua_commercial_opted_in": "2020-11-29T12:45:10" } ] send_it.device_types = [ "email" ] send_it.campaigns = ["winter sale", "west coast"] send_it.notification = email_notification.email_override send_it.create_and_send ``` *Example Create and Send a message for email with stored template* ```http POST /api/create-and-send HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "create_and_send" : [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22", "name": "New Person, Esq.", "location": "City, State" }, { "ua_address" : "ben@example.com", "ua_commercial_opted_in": "2020-11-29T12:45:10", "name": "Ben Wyatt", "location": "Pawnee, IN" } ] }, "device_types": [ "email" ], "notification": { "email": { "bcc": [ "blind@example.com" ], "message_type": "commercial", "reply_to": "no-reply@airship.com", "sender_address": "team@airship.com", "sender_name": "Airship", "template": { "template_id": "9335bb2a-2a45-456c-8b53-42af7898236a" } } } } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "67c65146-c27f-431f-b54a-83aca694fdd3", "push_ids": [ "c0eead17-333b-4f86-8a42-9fb7be1ed627" ], "message_ids": [], "content_urls": [] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); EmailChannel newChannel = EmailChannel.newBuilder() .setAddress("new@example.com") .setCommertialOptedIn(DateTime.parse("2020-11-29T10:34:22Z")) .build(); EmailChannel benChannel = EmailChannel.newBuilder() .setAddress("ben@example.com") .setTransactionalOptedIn(DateTime.parse("2020-11-29T12:45:10Z")) .build(); CreateAndSendAudience audience = new CreateAndSendAudience(EmailChannels.newBuilder() .addChannel(newChannel) .addChannel(benChannel) .build()); EmailTemplate template = EmailTemplate.newBuilder() .setTemplateId("9335bb2a-2a45-456c-8b53-42af7898236a") .build(); CreateAndSendEmailPayload createAndSendEmailPayload = CreateAndSendEmailPayload.newBuilder() .setEmailTemplate(template) .setMessageType(MessageType.TRANSACTIONAL) .setSenderName("Airship") .setSenderAddress("team@airship.com") .setReplyTo("no-reply@airship.com") .build(); Notification notification = Notification.newBuilder() .addDeviceTypeOverride(DeviceType.EMAIL, createAndSendEmailPayload) .build(); CreateAndSendPayload payload = CreateAndSendPayload.newBuilder() .setAudience(audience) .setNotification(notification) .build(); CreateAndSendRequest request = CreateAndSendRequest.newRequest(payload); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_notification = UA::EmailNotification.new(client: airship) email_notification.message_type = 'transactional' email_notification.reply_to = 'no-reply@airship.com' email_notification.sender_address = 'team@airship.com' email_notification.sender_name = 'Airship' email_notification.template_id = "9335bb2a-2a45-456c-8b53-42af7898236a" inline_template = email_notification.email_with_inline_template send_it = UA::CreateAndSend.new(client: airship) send_it.addresses = [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22" }, { "ua_address": "ben@example.com", "ua_commercial_opted_in": "2020-11-29T12:45:10" } ] send_it.device_types = [ "email" ] send_it.notification = inline_template send_it.create_and_send ``` *Example Create and Send with bulk ID for email* ```http POST /api/create-and-send HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "bulk_id": "26425d51-fbab-4ad8-bd5f-9560ee84b087" }, "device_types": [ "email" ], "notification": { "email": { "subject": "Welcome to the Winter Sale!", "html_body": "

Seasons Greetings {{name}}

Check out our winter deals!

Unsubscribe

", "plaintext_body": "Greetings {{name}}! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]", "message_type": "commercial", "sender_name": "Airship", "sender_address": "team@airship.com", "reply_to": "no-reply@airship.com" } }, "campaigns": { "categories": ["winter sale", "west coast"] } } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "67c65146-c27f-431f-b54a-83aca694fdd3", "push_ids": [ "c0eead17-333b-4f86-8a42-9fb7be1ed627" ], "message_ids": [], "content_urls": [] } ``` --- ## Create bulk send audience {#bulkuploadcreateandsendplatform} Upload a CSV to obtain a `bulk_id` for sending messages. The CSV can contain: - Channel IDs for Upload and Send endpoints: [Send message with bulk ID](/docs/developer/rest-api/ua/operations/bulk-sending/#bulksendpush) or [Schedule message with bulk ID](/docs/developer/rest-api/ua/operations/bulk-sending/#schedulebulksendpush) - Email addresses, phone numbers, or Open channel addresses for Create and Send endpoints: [Create and Send a message](/docs/developer/rest-api/ua/operations/bulk-sending/#createandsend) or [Schedule a Create and Send message](/docs/developer/rest-api/ua/operations/bulk-sending/#schedulecreateandsendoperations) See [Bulk sending](/docs/guides/audience/segmentation/bulk-sending/) for CSV formatting requirements. [Jump to examples ↓](#bulkuploadcreateandsendplatform-examples) ### `POST /api/bulk/{platform_name}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `platform_name` | `string` | Required | The audience channel platform. For open platforms, format the `{platform_name}` as `open/{open_platform_name}`. Possible values: `android`, `amazon`, `ios`, `web`, `sms`, `email`, `open_platform_name` | **Request body** **Content-Type:** `text/csv` Type: `string` **Responses** **`200`** The CSV was uploaded successfully and is now being processed. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`bulk_id`** `string` A unique string that identifies the audience provided in the CSV for bulk sending. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`field_names`** `array[string]` A list of the field names found in the CSV. - **`ok`** `boolean` Success. **`400`** Bad Request. Parsing or validating the request failed. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example create bulk send audience request for email* ```http POST /api/bulk/email HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv ua_address,ua_commercial_opted_in someone@example.com,2024-04-01T18:45:30 else@example.com,2024-04-21T16:13:01 ``` *Example create bulk send audience request for SMS* ```http POST /api/bulk/sms HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv ua_msisdn,ua_sender,ua_opted_in 15035551212,55555,2024-04-01T18:45:30 15031215555,55555,2024-04-21T16:13:01 ``` *Example create bulk send audience request for email with merge data fields* ```http POST /api/bulk/email HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv ua_address,ua_commercial_opted_in,name,city someone@example.com,2024-04-01T18:45:30,Joe Someone,Portland else@example.com,2024-04-21T16:13:01,Sir Else,Seattle ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "bulk_id": "26425d51-fbab-4ad8-bd5f-9560ee84b087", "field_names": ["ua_address", "ua_commercial_opted_in", "name", "city"] } ``` *Example create bulk send audience request for email* ```http POST /api/bulk/email HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv ua_channel_id 26bbfba4-f70a-4093-ab63-38d9123f6b23 89099449-6032-4821-8f1c-fd0892fdc609 ``` *Example create bulk send audience request for email with merge data fields* ```http POST /api/bulk/email HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv ua_channel_id,name,city 26bbfba4-f70a-4093-ab63-38d9123f6b23,2018-04-01T18:45:30,Joe Someone,Portland 89099449-6032-4821-8f1c-fd0892fdc609,2018-04-21T16:13:01,Sir Else,Seattle ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "bulk_id": "26425d51-fbab-4ad8-bd5f-9560ee84b087", "field_names": ["ua_channel_id", "name", "city"] } ``` *Example create bulk send audience request for open platform* ```http POST /api/bulk/open/rcs HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv ua_address 17881e35-4dcc-4f72-a017-e5aca8bb85f5 47745e49-099d-48d7-a489-563a2ae7497d 03079fe7-a013-4a22-9c1b-bca350a3e3fb 8a9b3ebc-010c-41c1-9484-6395b201dffe 65fefb71-c38e-4af8-9d6f-ec8bfcefd999 6e6fc2ee-722a-4729-86c3-f6d289373c41 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "bulk_id": "26425d51-fbab-4ad8-bd5f-9560ee84b087", "field_names": ["ua_address"] } ``` *Example create bulk send audience request for open channels* ```http POST /api/bulk/open/rcs HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv ua_channel_id 26bbfba4-f70a-4093-ab63-38d9123f6b23 89099449-6032-4821-8f1c-fd0892fdc609 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "bulk_id": "26425d51-fbab-4ad8-bd5f-9560ee84b087", "field_names": ["ua_channel_id"] } ``` --- ## Schedule a Create and Send message {#schedulecreateandsendoperations} Schedule a [Create and Send message](/docs/developer/rest-api/ua/operations/bulk-sending/#createandsend). Unknown identifiers are registered as new channels. This endpoint supports two audience methods: - `create_and_send` array: For smaller audiences, provide email addresses, MSISDNs, or Open channel addresses directly in the request. - `bulk_id`: For larger audiences, upload a CSV using the [Create bulk send audience](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) endpoint to obtain a `bulk_id`, then reference it in this request. Existing channels that are `opted_in` or have a newer `opted_in` value in the payload receive the message but are not re-registered. You cannot update `opted_in` values for existing channels through this endpoint. Note: This endpoint also accepts Channel IDs for app or web via `bulk_id`, but this works identically to [Schedule message with bulk ID](/docs/developer/rest-api/ua/operations/bulk-sending/#schedulebulksendpush). [Jump to examples ↓](#schedulecreateandsendoperations-examples) ### `POST /api/schedules/create-and-send` {{< warning >}} Duplicate addresses in the `create_and_send` array might receive redundant notifications or fewer notifications than expected. You should remove duplicate addresses from your request before sending a Create and Send message. {{< /warning >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** The request is much like other Create and Send operations, with a leading `schedule` object. The standard Create and Send payload sits inside a `push` object. **Content-Type:** `application/json` - **`name`** `string` A name for the schedule. - **`push`** `object` **REQUIRED** **One of:** - [Create and Send to email channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#email) The payload for a Create and Send operation to email channels. When sending to email channels, `device_types` must be set to `email`. - [Create and Send to SMS channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#sms) The payload for a Create and Send operation to SMS channels. When sending to SMS channels, `device_types` must be set to `sms`. - [Create and Send MMS notification]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#mms) The payload for a Create and Send operation that sends a multimedia payload (MMS) to SMS channels. When sending an MMS payload, `device_types` must be set to `mms`. - [Create and Send to open channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#open) The payload for a Create and Send operation to open channels. When sending to open channels, the `device_type` must be set to `open::`. - **`schedule`** `object` **REQUIRED** Similar to other schedule objects. However, Create and Send requests support `scheduled_time` only. **OBJECT PROPERTIES** - **`scheduled_time`** `string` **REQUIRED** The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when you want to perform your Create and Send operation. Users will receive the notification as soon as possible after the specified date-time. Format: `date-time` **Responses** **`202`** Because this operation sends messages, a successful response is nearly identical to a `/api/push` response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`content_urls`** `array[string]` An array of URLs where the push payload contains a landing page action. Min items: 0, Max items: 100 - **`localized_ids`** `array[string]` An array of identifiers used for reporting. Each ID represents a localized message (push object with `localizations` array). - **`message_ids`** `array[string]` An array of message IDs, each uniquely identifying a Message Center message. - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`push_ids`** `array[string]` An array of push IDs, each uniquely identifying a push. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example scheduled Create and Send message* ```http POST /api/schedules/create-and-send HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "schedule": { "scheduled_time" : "2020-11-11T12:00:00" }, "name" : "scheduled winter sale email", "push" : { "audience": { "create_and_send" : [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22" }, { "ua_address" : "ben@example.com", "ua_commercial_opted_in": "2020-11-29T12:45:10" } ] }, "device_types" : [ "email" ], "notification" : { "email": { "subject": "Welcome to the Winter Sale! ", "html_body": "

Seasons Greetings

Check out our winter deals!

Unsubscribe

", "plaintext_body": "Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]", "message_type": "commercial", "sender_name": "Airship", "sender_address": "team@airship.com", "reply_to": "no-reply@airship.com" } }, "campaigns": { "categories": ["winter sale", "west coast"] } } } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "67c65146-c27f-431f-b54a-83aca694fdd3", "push_ids": [ "8cf8b2a5-7655-40c2-a500-ff498e60453e" ], "schedule_urls": [ "http://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed109" ], "schedules": [ { "push": { "audience": { "create_and_send": [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22" }, { "ua_address": "ben@example.com", "ua_commercial_opted_in": "2020-11-29T12:45:10" } ] }, "device_types": [ "email" ], "notification": { "campaigns": { "categories": [ "winter sale", "west coast" ] }, "email": { "html_body": "

Seasons Greetings

Check out our winter deals!

Unsubscribe

", "message_type": "commercial", "plaintext_body": "Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]", "reply_to": "no-reply@airship.com", "sender_address": "team@airship.com", "sender_name": "Airship", "subject": "Welcome to the Winter Sale! " } } }, "schedule": { "scheduled_time": "2020-11-11T12:00:00" }, "url": "http://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed109" } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); String htmlBodyString = "

Seasons Greetings

Check out our winter deals!

Unsubscribe

"; String plaintextBodyString = "Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]"; EmailChannel newChannel = EmailChannel.newBuilder() .setAddress("new@example.com") .setCommertialOptedIn(DateTime.parse("2020-11-29T10:34:22Z")) .build(); EmailChannel benChannel = EmailChannel.newBuilder() .setAddress("ben@example.com") .setTransactionalOptedIn(DateTime.parse("2020-11-29T12:45:10Z")) .build(); CreateAndSendAudience audience = new CreateAndSendAudience(EmailChannels.newBuilder() .addChannel(newChannel) .addChannel(benChannel) .build()); CreateAndSendEmailPayload createAndSendEmailPayload = CreateAndSendEmailPayload.newBuilder() .setSubject("Welcome to the Winter Sale! ") .setHtmlBody(htmlBodyString) .setPlaintextBody(plaintextBodyString) .setMessageType(MessageType.TRANSACTIONAL) .setSenderName("Airship") .setSenderAddress("team@airship.com") .setReplyTo("no-reply@airship.com") .build(); Notification notification = Notification.newBuilder() .addDeviceTypeOverride(DeviceType.EMAIL, createAndSendEmailPayload) .build(); Campaigns campaign = Campaigns.newBuilder() .addCategory("winter sale") .addCategory("west coast") .build(); CreateAndSendPayload payload = CreateAndSendPayload.newBuilder() .setAudience(audience) .setNotification(notification) .setCampaigns(campaign) .build(); CreateAndSendSchedulePayload schedulePayload = CreateAndSendSchedulePayload.newBuilder() .setPayload(payload) .setScheduleTime(DateTime.parse("2020-11-11T12:00:00")) .setName("scheduled winter sale email") .build(); CreateAndSendScheduleRequest scheduleRequest = CreateAndSendScheduleRequest.newRequest(schedulePayload) Response response = client.execute(scheduleRequest); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_notification = UA::EmailNotification.new(client: airship) email_notification.bypass_opt_in_level = false email_notification.html_body = "

Seasons Greetings

Check out our winter deals!

Unsubscribe

" email_notification.message_type = 'transactional' email_notification.plaintext_body = 'Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]' email_notification.reply_to = 'no-reply@airship.com' email_notification.sender_address = 'team@airship.com' email_notification.sender_name = 'Airship' email_notification.subject = 'Welcome to the Winter Sale!' override = email_notification.email_override send_it = UA::CreateAndSend.new(client: airship) send_it.addresses = [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-10-28T10:34:22" } ] send_it.device_types = [ "email" ] send_it.campaigns = ["winter sale", "west coast"] send_it.notification = email_notification.email_override send_it.name = "scheduled winter sale email" send_it.scheduled_time = "2020-12-08T11:06:00" send_it.schedule ``` *Example scheduled Create and Send with bulk ID* ```http POST /api/schedules/create-and-send HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "schedule": { "scheduled_time": "2020-11-11T12:00:00" }, "name": "scheduled winter sale email", "push": { "audience": { "bulk_id": "26425d51-fbab-4ad8-bd5f-9560ee84b087" }, "device_types": [ "email" ], "notification": { "email": { "subject": "Welcome to the Winter Sale!", "html_body": "

Seasons Greetings {{name}}

Check out our winter deals!

Unsubscribe

", "plaintext_body": "Greetings {{name}}! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]", "message_type": "commercial", "sender_name": "Airship", "sender_address": "team@airship.com", "reply_to": "no-reply@airship.com" } }, "campaigns": { "categories": ["winter sale", "west coast"] } } } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "67c65146-c27f-431f-b54a-83aca694fdd3", "schedule_urls": [ "http://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed109" ] } ``` --- ## Schedule message with bulk ID {#schedulebulksendpush} Schedule a message to existing channels using a `bulk_id`. Inactive channels are dropped. Before calling this endpoint, obtain a `bulk_id` from the [Create bulk send audience](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) endpoint. [Jump to examples ↓](#schedulebulksendpush-examples) ### `POST /api/schedules/bulk-send` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** A Send a message with bulk ID payload. **Content-Type:** `application/json` [Scheduled bulk send object]({{< ref "/developer/rest-api/ua/schemas/bulk-sending/" >}}#scheduledbulksendobject) **Responses** **`202`** The push notification has been accepted for processing. The response contains `push_id`, `message_id`, and/or `content_url` arrays based on the type of push. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`content_urls`** `array[string]` An array of URLs where the push payload contains a landing page action. Min items: 0, Max items: 100 - **`localized_ids`** `array[string]` An array of identifiers used for reporting. Each ID represents a localized message (push object with `localizations` array). - **`message_ids`** `array[string]` An array of message IDs, each uniquely identifying a Message Center message. - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`push_ids`** `array[string]` An array of push IDs, each uniquely identifying a push. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`429`** Too many requests hit the API too quickly. For example, if we are not ready to create a channel for this payload; e.g., it is rate limited. You should wait before retrying the channel creation. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example schedule message with bulk ID* ```http POST /api/schedules/bulk-send HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3; Content-type: application/json { "schedule": { "scheduled_time" : "2024-11-07T12:00:00" }, "name" : "scheduled bulk send", "push" : { "audience" : { "bulk_id" : "36d5a261-0454-40f5-b952-942c4b2b0f22" }, "device_types" : [ "android" ], "notification" : { "alert" : "Hope you voted" }, "campaigns": { "categories": ["midterms2024", "getoutthevote2024"] } } } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "67c65146-c27f-431f-b54a-83aca694fdd3", "schedule_urls": [ "http://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed109" ], "schedules": [ { "url": "http://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed109" "schedule": { "scheduled_time" : "2024-11-07T12:00:00" } "push": { "audience": { "bulk_id" : "36d5a261-0454-40f5-b952-942c4b2b0f22" }, "device_types" : [ "open::rcs" ], "notification" : { "alert" : "Welcome to the winter sale!!" }, "campaigns": { "categories": ["winter sale", "west coast"] } } } ], "push_ids": ["8cf8b2a5-7655-40c2-a500-ff498e60453e"] } ``` --- ## Send message with bulk ID {#bulksendpush} Send an immediate message to existing channels using a `bulk_id`. Inactive channels are dropped. Before calling this endpoint, obtain a `bulk_id` from the [Create bulk send audience](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) endpoint. [Jump to examples ↓](#bulksendpush-examples) ### `POST /api/bulk-send` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** A Send a message with bulk ID payload. **Content-Type:** `application/json` [Bulk send object]({{< ref "/developer/rest-api/ua/schemas/bulk-sending/" >}}#bulksendobject) **Responses** **`202`** The push notification has been accepted for processing. The response contains `push_id`, `message_id`, and/or `content_url` arrays based on the type of push. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`content_urls`** `array[string]` An array of URLs where the push payload contains a landing page action. Min items: 0, Max items: 100 - **`localized_ids`** `array[string]` An array of identifiers used for reporting. Each ID represents a localized message (push object with `localizations` array). - **`message_ids`** `array[string]` An array of message IDs, each uniquely identifying a Message Center message. - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`push_ids`** `array[string]` An array of push IDs, each uniquely identifying a push. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`429`** Too many requests hit the API too quickly. For example, if we are not ready to create a channel for this payload; e.g., it is rate limited. You should wait before retrying the channel creation. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example send message with bulk ID* ```http POST /api/bulk-send HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3; Content-type: application/json { "audience" : { "bulk_id" : "36d5a261-0454-40f5-b952-942c4b2b0f22" }, "device_types" : [ "android" ], "notification" : { "alert" : "Welcome to the winter sale!!" }, "campaigns": { "categories": ["winter sale", "west coast"] } } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "67c65146-c27f-431f-b54a-83aca694fdd3", "push_ids": [ "c0eead17-333b-4f86-8a42-9fb7be1ed627" ], "message_ids": [], "content_urls": [] } ``` --- ## Validate Create and Send payload {#validatecreateandsendpayload} Validate a [Create and Send](/docs/developer/rest-api/ua/operations/bulk-sending/#createandsend) payload without creating channels or sending messages. It only parses and validates your payload. [Jump to examples ↓](#validatecreateandsendpayload-examples) ### `POST /api/create-and-send/validate` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** **Content-Type:** `application/json` **One of:** - [Create and Send to email channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#email) The payload for a Create and Send operation to email channels. When sending to email channels, `device_types` must be set to `email`. - [Create and Send to SMS channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#sms) The payload for a Create and Send operation to SMS channels. When sending to SMS channels, `device_types` must be set to `sms`. - [Create and Send MMS notification]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#mms) The payload for a Create and Send operation that sends a multimedia payload (MMS) to SMS channels. When sending an MMS payload, `device_types` must be set to `mms`. - [Create and Send to open channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#open) The payload for a Create and Send operation to open channels. When sending to open channels, the `device_type` must be set to `open::`. **Responses** **`200`** The payload was valid. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example Validate Create and Send payload* ```http POST /api/create-and-send/validate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "create_and_send" : [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22" }, { "ua_address" : "ben@example.com", "ua_commercial_opted_in": "2020-11-29T12:45:10" } ] }, "device_types" : [ "email" ], "notification" : { "email": { "subject": "Welcome to the Winter Sale! ", "html_body": "

Seasons Greetings

Check out our winter deals!

Unsubscribe

", "plaintext_body": "Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]", "message_type": "commercial", "sender_name": "Airship", "sender_address": "team@airship.com", "reply_to": "no-reply@airship.com" } }, "campaigns": { "categories": ["winter sale", "west coast"] } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); String htmlBodyString = "

Seasons Greetings

Check out our winter deals!

Unsubscribe

"; String plaintextBodyString = "Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]"; EmailChannel newChannel = EmailChannel.newBuilder() .setAddress("new@example.com") .setCommertialOptedIn(DateTime.parse("2020-11-29T10:34:22Z")) .build(); EmailChannel benChannel = EmailChannel.newBuilder() .setAddress("ben@example.com") .setTransactionalOptedIn(DateTime.parse("2020-11-29T12:45:10Z")) .build(); CreateAndSendAudience audience = new CreateAndSendAudience(EmailChannels.newBuilder() .addChannel(newChannel) .addChannel(benChannel) .build()); CreateAndSendEmailPayload createAndSendEmailPayload = CreateAndSendEmailPayload.newBuilder() .setSubject("Welcome to the Winter Sale! ") .setHtmlBody(htmlBodyString) .setPlaintextBody(plaintextBodyString) .setMessageType(MessageType.TRANSACTIONAL) .setSenderName("Airship") .setSenderAddress("team@airship.com") .setReplyTo("no-reply@airship.com") .build(); Notification notification = Notification.newBuilder() .addDeviceTypeOverride(DeviceType.EMAIL, createAndSendEmailPayload) .build(); Campaigns campaign = Campaigns.newBuilder() .addCategory("winter sale") .addCategory("west coast") .build(); CreateAndSendPayload payload = CreateAndSendPayload.newBuilder() .setAudience(audience) .setNotification(notification) .setCampaigns(campaign) .build(); CreateAndSendRequest request = CreateAndSendRequest.newRequest(payload) .setValidateOnly(true); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_notification = UA::EmailNotification.new(client: airship) email_notification.bypass_opt_in_level = false email_notification.html_body = "

Seasons Greetings

Check out our winter deals!

Unsubscribe

" email_notification.message_type = 'transactional' email_notification.plaintext_body = 'Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]' email_notification.reply_to = 'no-reply@airship.com' email_notification.sender_address = 'team@airship.com' email_notification.sender_name = 'Airship' email_notification.subject = 'Welcome to the Winter Sale!' override = email_notification.email_override send_it = UA::CreateAndSend.new(client: airship) send_it.addresses = [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22" } ] send_it.device_types = [ "email" ] send_it.campaigns = ["winter sale", "west coast"] send_it.notification = email_notification.email_override send_it.validate ``` --- ## Validate message with bulk ID {#validatebulksendpush} Accept the same range of payloads as POSTing to [`/api/bulk-send`](/docs/developer/rest-api/ua/operations/bulk-sending/#bulksendpush), but parse and validate only, without sending any messages. Before calling this endpoint, obtain a `bulk_id` using the [Create bulk send audience](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) operation. [Jump to examples ↓](#validatebulksendpush-examples) ### `POST /api/bulk-send/validate` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** A single bulk send object. **Content-Type:** `application/json` [Bulk send object]({{< ref "/developer/rest-api/ua/schemas/bulk-sending/" >}}#bulksendobject) **Responses** **`200`** The payload was valid. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example validate message with bulk ID* ```http POST /api/bulk-send/validate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3; Content-type: application/json { "audience" : { "bulk_id" : "36d5a261-0454-40f5-b952-942c4b2b0f22" }, "device_types" : [ "android" ], "notification" : { "alert" : "Welcome to the winter sale!!" }, "campaigns": { "categories": ["winter sale", "west coast"] } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` --- # Channels > Channels are Airship's unique identifiers for addressing applications on iOS, Android, Fire OS, and web devices. ## Channel listing {#getchannels} List all channels registered to this app key, along with associated data and metadata. [Jump to examples ↓](#getchannels-examples) ### `GET /api/channels` {{< note >}} Tags added to a channel via the [Named Users tag endpoint](/docs/developer/rest-api/ua/operations/tags/#modifynamedusertags) will not appear with a request to this endpoint. To view those tags, you must [look up the Named User](/docs/developer/rest-api/ua/operations/named-users/#getnameduser) associated with the channel. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `limit` | `integer` | | The default limit is 1,000 channel objects returned per request. Set the limit to 1,000 or fewer in your API calls. Max: 1000 | **Responses** **`200`** Returns OK for success with the JSON response. Tags added to a channel using `/named_users/tags` are not returned from this endpoint. To view those tags, you must look up the Named User associated with the channel. Response headers: | Name | Type | Description | |------|------|-------------| | `Link` | `string` | Provides the URL to the current page of results. The query within the URL contains the `limit` (the number of results on the page) and `start` (the first `channel_id` in the result set) parameters. | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`channels`** `array` <[Channel listing object]({{< ref "/developer/rest-api/ua/schemas/channels/" >}}#channellistingobject)> An array of channel objects. - **`next_page`** `string` If there is more than one page of results, use this link to get the next page of results. Format: `url` Example: `https://go.urbanairship.com/api/channels?limit=1000&start=535ec31e-4b07-4b26-bead-a1c0e94e133c` - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/channels HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 Data-Attribute: channels Link: ; rel=next { "ok": true, "next_page": "https://go.urbanairship.com/api/channels?start=07AAFE44CD82C2F4E3FBAB8962A95B95F90A54857FB8532A155DE3510B481C13&limit=2", "channels": [ { "channel_id": "9c36e8c7-5a73-47c0-9716-99fd3d4197d5", "device_type": "android", "push_address": "FE66489F304DC75B8D6E8200DFF8A456E8DAEACEC428B427E9518741C92C6660", "opt_in": true, "installed": true, "background": true, "created": "2020-03-06T18:52:59", "last_registration": "2020-10-07T21:28:35", "named_user_id": "some_id_that_maps_to_your_systems", "alias": "null", "tags": [ "tag1", "tag2" ], "tag_groups": { "tag_group_1": ["tag1", "tag2"], "tag_group_2": ["tag1", "tag2"] }, "device_attributes": { "ua_device_os": "10", "ua_country": "US", "ua_device_model": "SM-G973U", "ua_local_tz": "America/Los_Angeles", "ua_app_version": "2020-02-01T002322-goat", "ua_location_settings": "true", "ua_language": "en", "ua_sdk_version": "12.2.0", "ua_carrier": "Verizon " }, "attributes": { "first_name": "Cool", "last_name": "Person", "birthdate": "1983-03-15T00:00:00", } }, { "channel_id": "bd36e8c7-5a73-47c0-9716-99fd3d4197d5", "device_type": "ios", "push_address": null, "opt_in": false, "installed": true, "background": true, "created": "2020-03-06T18:52:59", "last_registration": "2020-10-07T21:28:35", "named_user_id": "some_id_that_maps_to_your_systems", "alias": "null", "tags": [ "tag1", "tag2" ], "tag_groups": { "tag_group_1": ["tag1", "tag2"], "tag_group_2": ["tag1", "tag2"] }, "ios": { "badge": 0, "quiettime": { "start": null, "end": null }, "tz": null } } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ChannelRequest request = ChannelRequest.newRequest(); Response response = client.execute(request); ChannelView channels = response.getBody().get().getChannelView().get(); ``` ```python from urbanairship import ( BasicAuthClient, ChannelList ) client = BasicAuthClient( key='', secret='' ) channel_id = None for channel in ChannelList(client): channel_id = channel.channel_id print(channel.channel_id, channel.device_type, channel.tags, channel.push_address, channel.named_user_id, channel.opt_in) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') channel_list = UA::ChannelList.new(client: airship) channel_list.each do |channel| puts(channel) end puts(channel_list.count) ``` --- ## Channel lookup {#getchannel} Fetch an individual channel registered to the app key, along with associated data and metadata. [Jump to examples ↓](#getchannel-examples) ### `GET /api/channels/{channel_id}` {{< note >}} Tags added to a channel via the [Named Users tag endpoint](/docs/developer/rest-api/ua/operations/tags/#modifynamedusertags) will not appear with a request to this endpoint. To view those tags, you must [look up the Named User](/docs/developer/rest-api/ua/operations/named-users/#getnameduser) associated with the channel. {{< /note >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `channel_id` | `string` | Required | The unique channel identifier. | **Responses** **`200`** Tags added to a channel using `/named_users/tags` are not returned from this endpoint. To view those tags, you must look up the Named User associated with the channel. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`channel`** `object` A channel object. **One of:** - [Channel listing object]({{< ref "/developer/rest-api/ua/schemas/channels/" >}}#channellistingobject) Describes a channel listing object. - **Open channel object** `object` Describes an open channel. - **`address`** `string` The address to send push notifications to when `device_type` is `email` or `open`. Example: `email@example.com` - **`channel_id`** `string` The unique channel identifier for a device. Format: `uuid` Example: `9c36e8c7-5a73-47c0-9716-99fd3d4197d5` - **`created`** `string` The creation [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) of this channel. Format: `date-time` Read only: true - **`last_registration`** `string` The last registration [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) of this channel, if known. Format: `date-time` Nullable: true Read only: true - **`locale_country`** `string` The two-letter country locale short code. Will set the `ua_locale_country` tag group to the specified value. - **`locale_language`** `string` The two-letter language locale short code. Will set the `ua_locale_language` tag group to the specified value. - **`named_user_id`** `string` A customer-chosen ID that represents the device user, e.g., CRM ID. This ID cannot have leading or trailing whitespace. Min length: 1, Max length: 128 Example: `john_doe` Nullable: true - **`open`** `object` Contains options that apply when the `device_type` is set to `open`. **OBJECT PROPERTIES** - **`identifiers`** `object` A set of up to 100 key:value pairs representing identifiers for this channel in your own delivery systems and delivered as a part of webhook payloads. Example: `[object Object]` - **`old_address`** `string` If a channel exists for the value of `old_address`, replaces that channel's address with the value of `address`. Use infrequently, such as when an end user's phone number or email address permanently changes. - **`open_platform_name`** `string` The name of the open channel that this `channel_id` is registered on. Example: `Slack` - **`opt_in`** `boolean` If true, the channel is opted in to push notifications. If false, it is not. - **`set_tags`** `boolean` When `true`, replaces all device tags on the channel with the set provided in `"tags"`. When `false` or absent, the `"tags"` set is unioned with existing device tags. - **`tag_groups`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> One or more tag group objects (including [Device Property Tags](/docs/reference/device-property-tags/)) associated with this channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`tags`** `array[string]` An array of tags associated with this channel. Min items: 0, Max items: 1000 Example: `Federer fan,Messi fan` - **`timezone`** `string` An IANA tzdata identifier for the time zone as a string, e.g., `"America/Los_Angeles"`. Will set the `timezone` tag group tag with the specified value. - **`type`** `string` Specifies the device platform for a channel. Possible values: `open` - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/channels/9c36e8c7-5a73-47c0-9716-99fd3d4197d5 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 Data-Attribute: channel { "ok": true, "channel": { "channel_id": "9c36e8c7-5a73-47c0-9716-99fd3d4197d5", "device_type": "ios", "installed": true, "opt_in": false, "background": true, "push_address": "FE66489F304DC75B8D6E8200DFF8A456E8DAEACEC428B427E9518741C92C6660", "created": "2020-08-08T20:41:06", "last_registration": "2020-05-01T18:00:27", "named_user_id": "some_id_that_maps_to_your_systems", "alias": null, "tags": [ "tag1", "tag2" ], "tag_groups": { "tag_group_1": ["tag1", "tag2"], "tag_group_2": ["tag1", "tag2"] }, "ios": { "badge": 0, "quiettime": { "start": null, "end": null }, "tz": "America/Los_Angeles" }, "open_tracking_opted_in": "2022-11-26T00:00:00", "open_tracking_opted_out": "2022-12-11T00:00:00", "click_tracking_opted_in": "2022-11-26T00:00:00", "click_tracking_opted_out": "2022-12-11T00:00:00" } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ChannelRequest request = ChannelRequest.newRequest("9c36e8c7-5a73-47c0-9716-99fd3d4197d5"); Response response = client.execute(request); ChannelView channel = response.getBody().get().getChannelView().get(); ``` ```python from urbanairship import ( BasicAuthClient, ChannelInfo ) client = BasicAuthClient( key='', secret='' ) channel = ChannelInfo(client).lookup('9c36e8c7-5a73-47c0-9716-99fd3d4197d5') print(channel.channel_id, channel.device_type, channel.tags, channel.push_address, channel.named_user_id, channel.opt_in) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') channel_client = UA::ChannelInfo.new(client: airship) channel_info = channel_client.lookup(uuid: '9c36e8c7-5a73-47c0-9716-99fd3d4197d5') puts(channel_info) ``` *Example open channel lookup response with all optional keys* ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 Data-Attribute: channel { "ok": true, "channel": { "channel_id": "b8f9b663-0a3b-cf45-587a-be880946e881", "type": "open", "opt_in": true, "address": "example@example.com", "created": "2013-08-08T20:41:06", "last_registration": "2014-05-01T18:00:27", "named_user_id": "john_doe_123", "tags": ["asdf"], "tag_groups": { "timezone" : ["America/Los_Angeles"], "locale_country" : ["US"], "locale_language" : ["en"], "tag_group_1" : ["tag1", "tag2"], "tag_group_2" : ["tag1", "tag2"] }, "open" { "open_platform_name": "email", "identifiers": { "com.example.external_id": "df6a6b50-9843-7894-1235-12aed4489489" } } } } ``` *Example open channel lookup response with only required keys* ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 Data-Attribute: channel { "ok": true, "channel": { "channel_id": "b8f9b663-0a3b-cf45-587a-be880946e881", "type": "open", "opt_in": false, "address": "example@example.com", "created": "2013-08-08T20:41:06", "last_modified": "2014-05-01T18:00:27", "tags": [], "tag_groups" {}, "open": { "open_platform_name": "email" } } } ``` --- ## Channel tags {#modifychanneltags} Add, remove, or set tags on a channel. [Jump to examples ↓](#modifychanneltags-examples) ### `POST /api/channels/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per channel. Adding more than 1,000 tags per channel can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per channel, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Adds the specified tags to the channel. Tags that are already present are not modified/removed as a result of this operation. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** Specifies one or more channels that you want to apply tag operations to. **OBJECT PROPERTIES** - **`amazon_channel`** `array[string]` The unique channel identifier for a Fire OS device. Min items: 1, Max items: 1000 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`android_channel`** `array[string]` The unique channel identifier for an Android device. Min items: 1, Max items: 1000 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`channel`** `array[string]` The unique channel identifier for `email`, `sms`, `open`, or `web` device types. Min items: 1, Max items: 1000 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`ios_channel`** `array[string]` The unique channel identifier for an iOS device. Min items: 1, Max items: 1000 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Removes the specified tags from the channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Assigns a list of tags exactly. Any previously set tags that are not in this current list will be removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** Returns OK for success. If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 is returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If true, your request was processed normally. - **`warnings`** `array[string]` Returned when some tag groups could not be updated. Contains a string indicating each tag group that could not be updated and the reason the update failed. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/tags HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "ios_channel": "b8f9b663-0a3b-cf45-587a-be880946e881", "android_channel": "13863b3c-f860-4bbf-a9f1-4d785379b8a2" }, "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "warnings": ["The following tag groups do not exist: my_fav_tag_group2", "The following tag groups are deactivated: my_fav_tag_group3"] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ChannelTagRequest request = ChannelTagRequest.newRequest() .addIOSChannel("b8f9b663-0a3b-cf45-587a-be880946e881") .addAndroidChannel("13863b3c-f860-4bbf-a9f1-4d785379b8a2") .addTags("my_fav_tag_group1", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("my_fav_tag_group2", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("my_fav_tag_group3", ImmutableSet.of("tag1", "tag2", "tag3")); Response response = client.execute(request); ``` ```python import urbanairship as ua client = ua.BasicAuthClient('', '') channel_tags = ua.devices.ChannelTags(client) ios_audience = ['b8f9b663-0a3b-cf45-587a-be880946e881'] android_audience = ['13863b3c-f860-4bbf-a9f1-4d785379b8a2'] channel_tags.set_audience(ios_audience, android_audience ) channel_tags.add('my_fav_tag_group1', ['tag1', 'tag2', 'tag3']) channel_tags.remove('my_fav_tag_group2', 'tag4') channel_tags.send() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') channel_tags = UA::ChannelTags.new(client: airship) ios_audience = 'b8f9b663-0a3b-cf45-587a-be880946e881' android_audience = '13863b3c-f860-4bbf-a9f1-4d785379b8a2' channel_tags.set_audience( ios: ios_audience, android: android_audience ) channel_tags.add(group_name: 'my_fav_tag_group1', tags: ['tag1', 'tag2', 'tag3']) channel_tags.remove(group_name: 'my_fav_tag_group2', tags: 'tag4') channel_tags.send_request ``` --- ## Set or remove attributes on channels {#modifychannelattributes} Set or remove attributes on a channel. Aside from Airship's [default attributes](/docs/reference/data-collection/attributes/#default-attributes), you must [define attributes in the Airship dashboard](/docs/guides/audience/attributes/adding/) before you can set them on channels. [Jump to examples ↓](#modifychannelattributes-examples) ### `POST /api/channels/attributes` {{< important >}} Use the [Named Users endpoint](/docs/developer/rest-api/ua/operations/named-users/#modifynameduserattributes) to set or remove attributes on Named Users. {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`attributes`** `object` <[Attribute assignment]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#attributesobject)> **REQUIRED** - **`audience`** `object` **REQUIRED** The channel(s) you want to set or remove attributes for. **OBJECT PROPERTIES** - **`amazon_channel`** `object` The unique channel identifier used to target a Fire OS device. **OBJECT PROPERTIES** - **`amazon_channel`** `object` **REQUIRED** **One of:** - `string` - `array` - **`android_channel`** `object` The unique channel identifier used to target an Android device. **OBJECT PROPERTIES** - **`android_channel`** `object` **REQUIRED** **One of:** - `string` - `array` - **`channel`** `object` The unique channel identifier used to target an open channel device or web device, i.e., web browser. **OBJECT PROPERTIES** - **`channel`** `object` **REQUIRED** **One of:** - `string` - `array` - **`email_address`** `array[string]` The unique channel identifier used to target an email address. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`ios_channel`** `object` The unique channel identifier used to target an iOS device. **OBJECT PROPERTIES** - **`ios_channel`** `object` **REQUIRED** **One of:** - `string` - `array` - **`sms_id`** `object` Selects a single SMS device. The `msisdn` must be `opted_in` to receive notifications. **OBJECT PROPERTIES** - **`msisdn`** `string` **REQUIRED** The recipient phone number. Min length: 1, Max length: 128 - **`sender`** `string` **REQUIRED** The sender that the app is configured to send SMS messages from. Min length: 1, Max length: 128 - **`web_channel`** `array[string]` The unique channel identifier used to target a web device. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` **Responses** **`200`** The operation was successful. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If true, your request was successful. - **`warning`** `string` Alerts you if your request could not be processed. You may receive a 200 with a warning if you provide a `value` that does not match your attribute type. For example, an attribute that expects a numeric value will allow a value of "25" but fail if you input "twenty-five". **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/attributes HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "android_channel": ["13863b3c-f860-4bbf-a9f1-4d785379b8a2"] }, "attributes": [ { "action": "set", "key": "major_league", "value": "sf_giants" }, { "action": "remove", "key": "minor_league" }, { "action": "set", "key": "position", "value": "LF" }, { "action": "set", "key": "specialData", "value": { "timestamp": "1983-03-15 10:00:00", "specialties": [ { "specialty": { "name": "golden", "property": "small" } }, { "specialty": { "name": "silver", "property": "medium" } } ] } } ] } ``` ```python from urbanairship import ( BasicAuthClient, Attribute ) import json client = BasicAuthClient( key='', secret='' ) set_major_league = Attribute( action="set", key="major_league", value="sf_giants" ) remove_minor_league = Attribute( action="remove", key="minor_league" ) set_position = Attribute( action="set", key="position", value="LF" ) specialties_string = "{" + \ " \"timestamp\": \"1983-03-15 10:00:00\"," + \ " \"specialties\": [{" + \ " \"specialty\": {" + \ " \"name\": \"golden\"," + \ " \"property\": \"small\"" + \ " }" + \ " }," + \ " {" + \ " \"specialty\": {" + \ " \"name\": \"silver\"," + \ " \"property\": \"medium\"" + \ " }" + \ " }" + \ " ]" + \ "}" specialties_json = json.loads(specialties_string) specialties = Attribute( action="set", key="specialties", value=specialties_json ) modifications = Attribute.ModifyAttributes( client=client, attributes=[set_major_league, remove_minor_league, set_position], channel="13863b3c-f860-4bbf-a9f1-4d785379b8a2" ) modifications.send() ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Attribute setMajorLeague = Attribute.newBuilder() .setAction(AttributeAction.SET) .setKey("major_league") .setValue("sf_giants") .build(); Attribute removeMinorLeague = Attribute.newBuilder() .setAction(AttributeAction.REMOVE) .setKey("minor_league") .build(); Attribute setPosition = Attribute.newBuilder() .setAction(AttributeAction.SET) .setKey("position") .setValue("LF") .build(); String specialtiesStr = "{" + " \"timestamp\": \"1983-03-15 10:00:00\"," + " \"specialties\": [{" + " \"specialty\": {" + " \"name\": \"golden\"," + " \"property\": \"small\"" + " }" + " }," + " {" + " \"specialty\": {" + " \"name\": \"silver\"," + " \"property\": \"medium\"" + " }" + " }" + " ]" + "}"; JSONObject specialtiesJson = new JSONObject(specialtiesStr); Attribute setSpecialties = Attribute.newBuilder() .setAction(AttributeAction.SET) .setKey("specialties") .setValue(specialtiesJson) .build(); ChannelAttributesPayload payload = ChannelAttributesPayload.newBuilder() .addAttribute(setMajorLeague) .addAttribute(removeMinorLeague) .addAttribute(setPosition) .setAudience(AttributeAudience.newBuilder() .addDeviceId(AttributeAudienceType.ANDROID_CHANNEL, "13863b3c-f860-4bbf-a9f1-4d785379b8a2") .build()) .build(); ChannelAttributesRequest request = ChannelAttributesRequest.newRequest(payload); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') channel_info = UA::ChannelInfo.new(client: airship) channel_info.audience = {"android_channel": '13863b3c-f860-4bbf-a9f1-4d785379b8a2'} channel_info.attributes = { "action": "set", "key": "major_league", "value": "sf_giants" } channel_info.set_attributes ``` *Example request with dates and numbers* ```http POST /api/channels/attributes HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "android_channel": ["13863b3c-f860-4bbf-a9f1-4d785379b8a2"] }, "attributes": [ { "action": "set", "key": "birthday", "value": "1983-03-15 10:00:00" }, { "action": "set", "key": "fav_number", "value": 42 }, { "action": "remove", "key": "another_attribute" } ] } ``` --- ## Subscribe or unsubscribe channels to/from subscription lists {#modifychannelsubscriptions} Subscribe or unsubscribe channels to/from Subscription Lists. [Jump to examples ↓](#modifychannelsubscriptions-examples) ### `POST /api/channels/subscription_lists` {{< note >}} If you are using a single-channel Preference Center created before October 10, 2022, that has not been [migrated to user-level](/docs/guides/messaging/features/preference-centers/#migrating-to-a-user-level-preference-center), use the [`/api/channels/subscription_lists` endpoint](/docs/developer/rest-api/ua/operations/channels/#modifychannelsubscriptions) to add or remove individual channels to/from your subscription list. Otherwise, use the [Scoped Named User batch operations endpoint](/docs/developer/rest-api/ua/operations/named-users/#performnameduserscopedbatchoperations) to do so. {{< /note >}} {{< important >}} You must first [create a subscription list in the dashboard](/docs/guides/audience/segmentation/audience-lists/subscription/#creating-a-list), then you can refer to its ID when subscribing users. When subscribing users, if the list has not already been created in the dashboard, then the list will be created at the same time but will not be accessible from the dashboard; the list will available for API use only. {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` **All of:** - [Audience selector (max 100)]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#audienceselector100) An audience selector forms the expression that determines the set of channels to target. - `array` An array of Subscription List objects. **Responses** **`202`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/subscription_lists HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "subscription_lists": [ { "action":"subscribe", "list_id":"intriguing_ideas" }, { "action":"unsubscribe", "list_id":"animal_facts" } ], "audience": { "ios_channel": [ "b8f9b663-0a3b-cf45-587a-be880946e881" ], "email_address": [ "homer@example.com", "nick@example.com" ] } } ``` ```python import urbanairship as ua client = ua.BasicAuthClient('', '') subscription_list = ua.SubscriptionList(client) subscription_list.subscribe(list_id="intriguing_ideas", audience=ua.email("nick@example.com") ) subscription_list.unsubscribe(list_id="animal_facts", audience=ua.ios_channel( "b8f9b663-0a3b-cf45-587a-be880946e881" ) ) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SubscriptionList subscriptionList = SubscriptionList.newBuilder() .setListId("big_deals") .setAction(SubscriptionListAction.SUBSCRIBE) .build(); SubscriptionListPayload payload = SubscriptionListPayload.newBuilder() .addSubscriptionList(subscriptionList) .setAudience(ChannelAudience.newBuilder() .addDeviceId(ChannelAudienceType.ANDROID_CHANNEL, "002b4104-c94f-418d-be86-ead3214b3244").build()) .build(); SubscriptionListRequest request = SubscriptionListRequest.newRequest(payload); Response response = client.execute(request); ``` --- ## Uninstall channels {#uninstallchannels} Uninstalls a channel, removing it and all accompanying analytic data (including Performance Analytics) from Airship systems in accordance with data privacy law compliance. Uninstallation is handled automatically by the Airship SDK and push systems. If a user decides to opt in to communications again (either by using your app or other user preferences), they will create a new channel and a new set of analytic data. The value of a Channel ID may be the same as before however none of the associated metadata will persist when a user opts in again. A new Channel ID will be created if the user clears their browser’s cookies and data, deletes and reinstalls the app, etc. See [Individual Data Privacy Rights Under Data Privacy Laws](/docs/guides/audience/privacy/individual-data-privacy/) for more information about data privacy law compliance. [Jump to examples ↓](#uninstallchannels-examples) ### `POST /api/channels/uninstall` {{< note >}} Channel uninstallation, like channel creation, is an asynchronous operation and may take some time to complete. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` Type: `array` **Responses** **`202`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/uninstall HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json [ { "channel_id": "b8f9b663-0a3b-cf45-587a-be880946e881", "device_type": "ios" }, { "channel_id": "13863b3c-f860-4bbf-a9f1-4d785379b8a2", "device_type": "android" } ] ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, ChannelUninstall ) client = BasicAuthClient( key='', secret='' ) channel_uninstall = ChannelUninstall(client) channel = { "channel_id": 'b8f9b663-0a3b-cf45-587a-be880946e881', "device_type": "ios" } channel_uninstall.uninstall(channel) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') cu = UA::ChannelUninstall.new(client: airship) chans = [{"channel_id" => "b8f9b663-0a3b-cf45-587a-be880946e881", "device_type" => "ios"}, {"channel_id" => "13863b3c-f860-4bbf-a9f1-4d785379b8a2", "device_type" => "android"}] cu.uninstall(channels: chans) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Set channels = ImmutableSet.of( new ChannelUninstallDevice("00f74677-4616-4958-bd91-30e949814d2c", ChannelUninstallDeviceType.IOS), new ChannelUninstallDevice("007f7156-9b82-4cb6-a2f9-e2c8e7fce13d", ChannelUninstallDeviceType.ANDROID) ); ChannelUninstallPayload payload = ChannelUninstallPayload.newBuilder() .setChannels(channels) .build(); ChannelUninstallRequest request = ChannelUninstallRequest.newRequest(payload); Response response = client.execute(request); ``` --- # Contacts > Manage Contacts and query for subscription lists, channels, named users, and attributes associated with a Contact. ## Contact association {#associatecontact} Associate a channel, email address, or MSISDN with a Contact. The `contact_id` is created if it does not already exist. ### `POST /api/contacts/associate` {{< note >}} If the `channel_id`, `email_address`, or `msisdn` is already associated with a `contact_id`, this operation will do nothing and return a 200 status code and the existing `contact_id`. {{< /note >}} **Security:** - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): cnt **Request body** Contact association requires a `channel_id`, `email_address`, or `msisdn`. Do not provide more than one identifier type in the same request. You can associate up to 100 Channel IDs to a Contact. Channel creation is asynchronous, so when associating a newly created channel, both a Channel ID and a device type are required to prevent "channel does not exist" errors. **Content-Type:** `application/json` **One of:** - **`channel_id`** `string` **REQUIRED** The Channel ID you want to associate with a Contact. Format: `uuid` Example: `9c36e8c7-5a73-47c0-9716-99fd3d4197d5` - **`contact_id`** `string` **REQUIRED** A string value identifying the user, without leading or trailing whitespace. Min length: 1, Max length: 128 Example: `john_doe` - **`device_type`** `string` The device type of the channel. Possible values: `ios`, `android`, `amazon`, `web`, `open`, `email`, `sms` - **`contact_id`** `string` **REQUIRED** The existing Contact. Min length: 1, Max length: 128 Example: `john_doe` - **`email_address`** `string` **REQUIRED** The email address you want to associate with a Contact. Format: `email` Example: `user@example.com` **Responses** **`200`** The request was accepted. The `contact_id` is returned in the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) --- ## Contact disassociation {#disassociatecontact} Disassociates channel from a Contact with the option of also opting out. You can identify a channel by MSISDN, email address, or Channel ID. [Jump to examples ↓](#disassociatecontact-examples) ### `POST /api/contacts/disassociate/{contact_id}` **Security:** - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): cnt **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `contact_id` | `string` | Required | The Contact ID to disassociate from a channel. | **Request body** **Content-Type:** `application/json` - **`channel_id`** `string` The Channel ID to disassociate from the Contact. Format: `uuid` Example: `{{channel_id}}` - **`channel_type`** `string` **REQUIRED** The type of channel. Possible values: `sms`, `email`, `ios`, `android`, `amazon`, `web`, `open` - **`email_address`** `string` The email address to disassociate from the Contact. - **`msisdn`** `string` The mobile phone number to disassociate from the Contact. Must be numeric characters only, without leading zeros. 15 digits maximum. Max length: 15 - **`opt_out`** `boolean` Optional. True if the channel is to be opted out; otherwise false. - **`sender`** `string` A long or short code the app is configured to send from. For example, `12345`. **Responses** **`200`** The request was accepted. Response body: **Content-Type:** `application/json` - **`channel_id`** `string` Identifies the existing unique Channel ID. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`contact`** `string` Identifies the existing unique Contact ID. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`ok`** `boolean` Success. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example dissociate SMS channel from Contact by Channel ID* ```http POST /api/contacts/disassociate/eed87e83-2f2f-4919-bcb0-8c620e0fae40 HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel_type": "sms", "channel_id": "c8d58c64-7eb5-40ad-ad51-d39e05335c48" } ``` *Example dissociate SMS channel from Contact by sender ID and MSISDN* ```http POST /api/contacts/disassociate/eed87e83-2f2f-4919-bcb0-8c620e0fae40 HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel_type": "sms", "sender": "1234", "msisdn": "15035551234" } ``` *Example dissociate email channel from Contact by email address* ```http POST /api/contacts/disassociate/eed87e83-2f2f-4919-bcb0-8c620e0fae40 HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel_type": "email", "email_address": "abc@example.com" } ``` *Example dissociate email channel from Contact by email address with opt_out* ```http POST /api/contacts/disassociate/eed87e83-2f2f-4919-bcb0-8c620e0fae40 HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel_type": "email", "email_address": "abc@example.com", "opt_out": true } ``` *Example of a successful response* ```http HTTP/1.1 200 OK Content-Type: application/json { "ok": true, "contact": "eed87e83-2f2f-4919-bcb0-8c620e0fae40", "channel_id": "c8d58c64-7eb5-40ad-ad51-d39e05335c48" } ``` --- ## Contacts tags {#modifycontacttags} Add, remove, or set tags on a Contact. A single request body may contain add and/or remove objects or a single set field. At least one of the add, remove, or set objects must be present in a request. ### `POST /api/contacts/tags/` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per Contact. Adding more than 1,000 tags per Contact can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per Contact, and they will help you find an alternative. {{< /important >}} **Security:** - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): cnt **Request body** **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Add the list of tags to the Contacts, but do not remove any. If the tags are already present, they are not modified. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** The Contacts you want to associate/disassociate tags with. **OBJECT PROPERTIES** - **`contact_id`** `array[string]` Min items: 1, Max items: 1000 - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Remove the list of tags from the Contacts, but do not remove any others. If the tags are not currently present, nothing happens. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Set these tags for the audience. Any tags previously associated with the audience tags that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 will be returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` **REQUIRED** Set to `true` when status code is `200`. - **`tag_warnings`** `string` Warnings encountered when processing tags for this Contact. **`400`** Parsing or validating the request failed. You will see this error if the same tag is present in both the add and remove fields. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) --- ## Look up Contact ID by Channel ID {#getcontactidfromchannelid} Looks up a Contact ID for the given Channel ID. [Jump to examples ↓](#getcontactidfromchannelid-examples) ### `GET /api/contacts/lookup/channel/{channel_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): cnt **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `channel_id` | `string` | Required | The Channel ID for which to retrieve the associated Contact ID. | **Responses** **`200`** The request was accepted. Response body: **Content-Type:** `application/json` - **`contact_id`** `string` **REQUIRED** The resolved Contact ID. Format: `uuid` - **`is_anonymous`** `boolean` **REQUIRED** Specifies whether the Contact is anonymous or not. - **`ok`** `boolean` **REQUIRED** Set to `true` when status code is `200`. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example get Contact ID from a Channel ID * ```http GET /api/contacts/lookup/channel/164c3a13-9c75-4ea9-be2c-1bed2c97f9c3 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "contact_id": "7c24ebdd-ec06-47d4-9a56-ced8611f5b52", "is_anonymous": false } ``` --- ## Look up Contact ID by Named User ID {#getcontactidfromnameduserid} Looks up a Contact ID for the given Named User ID. [Jump to examples ↓](#getcontactidfromnameduserid-examples) ### `GET /api/contacts/lookup/named_user/{named_user_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): cnt **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `named_user_id` | `string` | Required | The URL-encoded Named User ID for which to retrieve the associated Contact ID. | **Responses** **`200`** The request was accepted. Response body: **Content-Type:** `application/json` - **`contact_id`** `string` **REQUIRED** The resolved Contact ID. Format: `uuid` - **`ok`** `boolean` **REQUIRED** Set to `true` when status code is `200`. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example get Contact ID from a Named User ID * ```http GET /api/contacts/lookup/named_user/90ae282f-f56e-4037-8174-482ef7e3e5f4 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "contact_id": "7c24ebdd-ec06-47d4-9a56-ced8611f5b52" } ``` --- ## Scoped Contact batch operations {#performscopedcontactbatchoperations} Performs one or more scoped operations on a Contact in a single request. The body is a scoped array, and each item has a scope and one or more operations. Behavior matches the equivalent single-operation APIs. For each scope: * Subscription list operations are supported. You can subscribe and/or unsubscribe the Contact to/from subscription lists for that scope, which is the same behavior as the subscription list APIs. * Tag operations are not supported. If `tags` is present in any scoped item, the request is rejected with 400 and an error indicating that tags are not allowed in this context. The following apply: * Set operations are not supported. * Failure to authorize on secure tags results in a 200 and warning. * Failure to find any valid tag groups results in a 200 and warning. * Failure to find any valid attributes results in a 200 and warning. [Jump to examples ↓](#performscopedcontactbatchoperations-examples) ### `POST /api/contacts/scoped/{contact_id}` {{< note >}} If you are using a single-channel Preference Center created before October 10, 2022, that has not been [migrated to user-level](/docs/guides/messaging/features/preference-centers/#migrating-to-a-user-level-preference-center), use the [`/api/channels/subscription_lists` endpoint](/docs/developer/rest-api/ua/operations/channels/#modifychannelsubscriptions) to add or remove individual channels to/from your subscription list. {{< /note >}} {{< important >}} The path parameter `contact_id` should be URL-encoded to ensure it is handled correctly. {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): cnt **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `contact_id` | `string` | Required | A string (UUID) value identifying the Contact with no leading or trailing whitespace. | **Request body** **Content-Type:** `application/json` - **`scoped`** `array` <[Contacts scoped batch item]({{< ref "/developer/rest-api/ua/schemas/contacts/" >}}#contactsscopedbatchitem)> An array of scopes, tags, and subscription lists. **Responses** **`200`** The request was accepted. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` **REQUIRED** Whether the operation was successful. - **`subscription_list_warnings`** `array[string]` Any warnings related to subscription list operations. - **`tag_warnings`** `array[string]` Any warnings related to tag operations. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example scoped contact batch operations * ```http POST /api/contacts/scoped/77721a11-7ffa-4362-9bdb-f27ca891f9de HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "scoped": [{ "scope": ["web", "email", "app"], "subscription_lists": { "subscribe": ["subscription_1", "subscription_2"], "unsubscribe": ["subscription_3"] } }] } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` --- ## Set or remove attributes on a Contact {#modifycontactattributes} Set or remove attributes on a Contact. A single request body may contain a `set` or `remove` field, or both, or a single `set` field. If both `set` and `remove` fields are present and the intersection of the attributes in these fields is not empty, then a `400` will be returned. If an attribute request is partially valid, i.e., at least one attribute exists, Airship returns a `200` with a warning about the attributes that failed to update. The attributes listed in the `warnings` string will be in CSV format. ### `POST /api/contacts/attributes` {{< note >}} Airship returns a `200` with a warning if you attempt to set attributes on a Contact that does not exist. {{< /note >}} {{< tip >}} If you wish to set attributes on multiple Contact at once, we recommend using [/api/channels/attributes](/docs/developer/rest-api/ua/operations/channels/#modifychannelattributes) which supports an `audience` object in the request body. {{< /tip >}} **Security:** - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): cnt **Request body** **Content-Type:** `application/json` Type: `array` **Responses** **`200`** Success. If an attribute request is partially valid, i.e., at least one attribute exists, Airship returns a `200` with a warning string containing a CSV list of attributes that failed to update. Airship also returns a `200` with a warning if you attempt to set attributes on a `contact_id`, even if the `contact_id` does not exist. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` Set to `true` when status code is `200`. - **`warnings`** `string` Warnings encountered when updating Contact attributes. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) --- # Content > Use the Content API to create content templates that can be sent in pushes and [managed in the Airship dashboard](/guides/personalization/content/templates/). ## Create content template {#createcontenttemplate} Create a new content template. [Jump to examples ↓](#createcontenttemplate-examples) ### `POST /api/content/templates` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): tpl **Request body** A single content template object. **Content-Type:** `application/json` [Content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#contenttemplateobject) **Responses** **`201`** The template was created. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The URI for the template, used for later updates or sends. | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If `true`, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`template_id`** `string` A unique string identifying the template, used to reference it when sending messages and in other operations. Format: `uuid` Example: `0f7704e9-5dc0-4f7d-9964-e89055701b0a` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example create email content template with snippet and feed references* ```http POST /api/content/templates HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "external_id": "welcome_message", "name": "Welcome Message", "description": "Our welcome message", "type": "email", "content": { "subject": "Welcome!", "html_body": "Hi, {{first_name}}! {{>footer}}", "plaintext_body": "Hi, {{first_name}}!" }, "snippet_references": { "snippets": [ { "name": "footer" } ] }, "feed_references": { "feeds": [ { "name": "featured_product" } ] } } ``` ```http HTTP/1.1 201 Created Location: https://go.urbanairship.com/api/content/templates/ef34a8d9-0ad7-491c-86b0-aea74da15161 Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "operation_id" : "9ce808c8-7176-45dc-b79e-44aa74249a5a", "template_id": "ef34a8d9-0ad7-491c-86b0-aea74da15161" } ``` --- ## Create or update content template by external ID {#updatecontenttemplatebyexternalid} Create or update a content template by its external ID. [Jump to examples ↓](#updatecontenttemplatebyexternalid-examples) ### `PUT /api/content/templates/external/{type}/{external_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): tpl **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `type` | `string` | Required | The message type for the template. Possible values: `email`, `sms`, `open`, `app`, `web`, `message_center` | | `external_id` | `string` | Required | The customer-defined external ID of the template. | **Request body** A partially defined content template object. **Content-Type:** `application/json` [Content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#contenttemplateobject) **Responses** **`200`** Returned if the template has been successfully updated. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If `true`, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example update content template by external ID* ```http PUT /api/content/templates/external/email/customer-defined-id HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name": "Welcome Message", "description": "Our welcome message", "content": { "subject": "Welcome!", "html_body": "Hi, {{first_name}}!", "plaintext_body": "Hi, {{first_name}}!" } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "operation_id" : "9ce808c8-7176-45dc-b79e-44aa74249a5a" } ``` --- ## Delete content template {#deletecontenttemplate} Delete a content template. [Jump to examples ↓](#deletecontenttemplate-examples) ### `DELETE /api/content/templates/{template_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): tpl **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `template_id` | `string` | Required | The UUID of the template. | **Responses** **`200`** The template with the given ID has been successfully deleted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If `true`, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example delete content template* ```http DELETE /api/content/templates/ef34a8d9-0ad7-491c-86b0-aea74da15161 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "operation_id" : "9ce808c8-7176-45dc-b79e-44aa74249a5a" } ``` --- ## Delete content template by external ID {#deletecontenttemplatebyexternalid} Delete a content template. [Jump to examples ↓](#deletecontenttemplatebyexternalid-examples) ### `DELETE /api/content/templates/external/{type}/{external_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): tpl **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `type` | `string` | Required | The message type for the template. Possible values: `email`, `sms`, `open`, `app`, `web`, `message_center` | | `external_id` | `string` | Required | The customer-defined external ID of the template. | **Responses** **`200`** The template with the given external ID has been successfully deleted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If `true`, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example delete content template by external ID* ```http DELETE /api/content/templates/external/email/customer-defined-id HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "operation_id" : "9ce808c8-7176-45dc-b79e-44aa74249a5a" } ``` --- ## List content templates {#listcontenttemplates} List all existing content templates. Returns an array of content template objects in the `content_templates` attribute. [Jump to examples ↓](#listcontenttemplates-examples) ### `GET /api/content/templates` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): tpl **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `page` | `integer` | | Specifies the desired page number. Defaults to 1. | | `page_size` | `integer` | | Specifies how many results to return per page. | | `sort` | `string` | | Specifies the name of the field you want to sort results by. Defaults to `created_at`. Possible values: `created_at`, `modified_at` | | `order` | `string` | | Specifies the sort order as ascending (`asc`) or descending (`desc`). Defaults to `asc`. Possible values: `asc`, `desc` | **Responses** **`200`** Returned on success, with the JSON representation of the content templates in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`content_templates`** `array` <[Content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#contenttemplateobject)> An array of content template objects. - **`count`** `integer` The number of content templates in the current response. This is effectively the page size. - **`next_page`** `string` There might be more than one page of results for this listing. When present, use this URL to fetch the next batch of results. Format: `url` - **`ok`** `boolean` **REQUIRED** Success. - **`prev_page`** `string` Link to the previous page, if available. Format: `url` - **`total_count`** `integer` The total number of content templates. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example list content templates* ```http GET /api/content/templates HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "count": 1, "total_count": 1, "content_templates": [ { "id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "external_id": "welcome_message", "name": "Welcome Message", "description": "Our welcome message", "type": "email", "content": { "subject": "Welcome!", "html_body": "Hi, {{first_name}}!", "plaintext_body": "Hi, {{first_name}}!" }, "created_at": "2020-08-17T11:10:02Z", "modified_at": "2020-08-17T11:10:02Z" } ], "next_page": null, "prev_page": null } ``` --- ## Look up a content template {#getcontenttemplate} Fetch a single content template using UUID. [Jump to examples ↓](#getcontenttemplate-examples) ### `GET /api/content/templates/{template_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): tpl **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `template_id` | `string` | Required | The UUID of the template. | **Responses** **`200`** Returned on success, with the JSON representation of the template in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`content_template`** `object` <[Content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#contenttemplateobject)> A reusable template containing fields for a message type. Can be referenced by its UUID or a customer-defined external ID. - **`ok`** `boolean` **REQUIRED** If `true`, the operation completed successfully and returns an expected response. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example look up content template* ```http GET /api/content/templates/ef34a8d9-0ad7-491c-86b0-aea74da15161 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "content_template": { "id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "external_id": "welcome_message", "name": "Welcome Message", "description": "Our welcome message", "type": "email", "content": { "subject": "Welcome!", "html_body": "Hi, {{first_name}}! {{>footer}}", "plaintext_body": "Hi, {{first_name}}!" }, "created_at": "2020-08-17T11:10:02Z", "modified_at": "2020-08-17T11:10:02Z", "snippets": [ { "name": "footer" } ] } } ``` --- ## Look up a content template by external ID {#getcontenttemplatebyexternalid} Fetch a single content template using external ID. [Jump to examples ↓](#getcontenttemplatebyexternalid-examples) ### `GET /api/content/templates/external/{type}/{external_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): tpl **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `type` | `string` | Required | The message type for the template. Possible values: `email`, `sms`, `open`, `app`, `web`, `message_center` | | `external_id` | `string` | Required | The customer-defined external ID of the template. | **Responses** **`200`** Returned on success, with the JSON representation of the template in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`content_template`** `object` <[Content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#contenttemplateobject)> A reusable template containing fields for a message type. Can be referenced by its UUID or a customer-defined external ID. - **`ok`** `boolean` **REQUIRED** If `true`, the operation completed successfully and returns an expected response. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example look up content template by external ID* ```http GET /api/content/templates/external/email/customer-defined-id HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "content_template": { "id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "external_id": "customer-defined-id", "name": "Welcome Message", "description": "Our welcome message", "type": "email", "content": { "subject": "Welcome!", "html_body": "Hi, {{first_name}}! {{>footer}}", "plaintext_body": "Hi, {{first_name}}!" }, "created_at": "2020-08-17T11:10:02Z", "modified_at": "2020-08-17T11:10:02Z", "snippets": [ { "name": "footer" } ] } } ``` --- ## Update content template {#updatecontenttemplate} Update a content template. [Jump to examples ↓](#updatecontenttemplate-examples) ### `PUT /api/content/templates/{template_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): tpl **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `template_id` | `string` | Required | The UUID of the template. | **Request body** A partially defined content template object. **Content-Type:** `application/json` [Content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#contenttemplateobject) **Responses** **`200`** Returned if the template has been successfully updated. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If `true`, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example update content template* ```http PUT /api/content/templates/ef34a8d9-0ad7-491c-86b0-aea74da15161 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name": "Welcome Message", "description": "Our welcome message", "content": { "subject": "Welcome!", "html_body": "Hi, {{first_name}}!", "plaintext_body": "Hi, {{first_name}}!" } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "operation_id" : "9ce808c8-7176-45dc-b79e-44aa74249a5a" } ``` --- # Custom Events > User events that occur outside of your app can be submitted to Airship for inclusion in analytics reporting, as triggers for Automation, or for export via Connect. These events can take place on the web, e.g., your website, social media, or in your back office systems such as CRM or POS software. Any event that can be associated with a mobile app user can be submitted as an Airship Custom Event. The events that you submit are associated with channels and are available to use as Custom Event triggers. ## Add Custom Events {#addcustomevents} Submit an externally-generated Custom Event, associated with a Channel ID or Named User, to Airship. You can use these events as Custom Event triggers for Automation or Sequences and can use handlebars to personalize messages using Custom Event properties (information in the `body.properties` object). [Jump to examples ↓](#addcustomevents-examples) ### `POST /api/custom-events` {{< note >}} * Requests complete validation before returning a response. * Requests are authenticated with a bearer token, which can provide access to this resource alone or to this resource and others. * The `name` value inside `body` must not contain any uppercase characters, or the event will be rejected with a 400 status code. {{< /note >}} **Security:** - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): evt **Request headers:** | Name | Type | Required | Description | |------|------|----------|-------------| | `X-UA-Appkey` | `string` | Required | The application key for your project. | **Request body** An array of Custom Event objects. **Content-Type:** `application/json` Type: `array` **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying the API interaction. You can use the `operation_id` in support requests if something goes wrong. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/custom-events HTTP/1.1 Authorization: Bearer X-UA-Appkey: Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json [ { "occurred": "2020-05-02T02:31:22", "user": { "named_user_id": "hugh.manbeing" }, "body": { "name": "purchased", "value": 239.85, "transaction": "886f53d4-3e0f-46d7-930e-c2792dac6e0a", "interaction_id": "your.store/us/en_us/pd/shoe/pid-11046546/pgid-10978234", "interaction_type": "url", "properties": { "description": "Sneaker purchase", "brand": "Victory Sneakers", "colors": [ "red", "blue" ], "items": [ { "text": "New Line Sneakers", "price": "$ 79.95" }, { "text": "Old Line Sneakers", "price": "$ 79.95" }, { "text": "Blue Line Sneakers", "price": "$ 79.95" } ], "name": "Hugh Manbeing", "userLocation": { "state": "CO", "zip": "80202" } }, "session_id": "22404b07-3f8f-4e42-a4ff-a996c18fa9f1" } } ] ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "8c61c0c4-95b0-45a6-bc38-733f7fcb8979" } ``` ```python from datetime import datetime from urbanairship import ( BearerTokenClient, CustomEvent ) client = BearerTokenClient( app_key='', token='' ) event = CustomEvent( client=client, name='purchased', user={'named_user_id': 'hugh.manbeing'}, interaction_type='url', interaction_id='your.store/us/en_us/pd/shoe/pid-11046546/pgid-10978234', value=239.85, transaction='886f53d4-3e0f-46d7-930e-c2792dac6e0a', session_id='22404b07-3f8f-4e42-a4ff-a996c18fa9f1', properties={ 'description': 'Sneaker purchase', 'brand': 'Victory Sneakers', 'colors': ['red', 'blue'], 'items': [ {'text': 'New Line Sneakers', 'price': '$ 79.95'}, {'text': 'Old Line Sneakers', 'price': '$ 79.95'}, {'text': 'Blue Line Sneakers', 'price': '$ 79.95'} ], 'name': 'Hugh Manbeing', 'userLocation': { 'state': 'CO', 'zip': '80202' } }, occurred=datetime(2020, 5, 2, 2, 31, 22) ) response = event.send() ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .setBearerToken("") .build(); CustomEventUser customEventUser = CustomEventUser.newBuilder() .setNamedUserId("hugh.manbeing") .build(); CustomEventPropertyValue customEventProperty = CustomEventPropertyValue.of("Victory Sneakers"); List items = new ArrayList<>(); items.add(CustomEventPropertyValue.of("New Line Sneakers")); items.add(CustomEventPropertyValue.of("Old Line Sneakers")); DateTime occurred = new DateTime(2020, 05, 02, 02, 31, 22, DateTimeZone.UTC); CustomEventBody customEventBody = CustomEventBody.newBuilder() .setName("purchased") .addPropertiesEntry("brand", customEventProperty) .addPropertiesEntry("items", CustomEventPropertyValue.of(items)) .build(); CustomEventPayload customEventPayload = CustomEventPayload.newBuilder() .setCustomEventBody(customEventBody) .setCustomEventUser(customEventUser) .setOccurred(occurred) .build(); CustomEventRequest customEventRequest = CustomEventRequest.newRequest(customEventPayload); Response response = client.execute(customEventRequest); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', token: '') example_events = [ UA.custom_events( body: UA.custom_events_body( interaction_id: "api/ua/#schemas-customeventobject", interaction_type: "url", name: "example", properties: { "who" => "Alf", "where" => "In the garage!", "from" => "Melmac" }, session_id: "8d168d40-bc9b-4359-800c-a546918354ac", transaction: "d768f61f-73ba-495f-9e16-b3b9c3b598b7", value: 1 ), occurred: "2021-10-01T00:00:00", user: UA.custom_events_user(named_user_id: "Gordon Shumway") ) ] event = Urbanairship::CustomEvents::CustomEvent.new(client: airship) event.events = example_events event.create ``` --- # Data Privacy Laws Compliance > Use Contact Management to record data privacy requests for your customers. ## Named Users uninstall {#uninstallnameduser} Disassociate and delete all channels associated with the named_user_id(s) and also delete the named_user_id(s). This call removes all channels associated with a Named User from Airship systems in compliance with data privacy laws. Uninstalling channels also removes accompanying analytic data (including Performance Analytics) from the system. See [Individual Data Privacy Rights Under Data Privacy Laws](/docs/guides/audience/privacy/individual-data-privacy/) for more information about data privacy law compliance. [Jump to examples ↓](#uninstallnameduser-examples) ### `POST /api/named_users/uninstall` {{< note >}} Channel uninstallation, like channel creation, is an asynchronous operation and may take some time to complete. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Request body** **Content-Type:** `application/json` - **`named_user_id`** `array[string]` **REQUIRED** Array of strings representing the named_user_id(s) you wish to be uninstalled. Must have between 1 to 100 items in the array with a 128 character/byte maximum per item. Min items: 1, Max items: 100 **Responses** **`200`** All channels have been deleted and disassociated from the Named User. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example delete all users and their associated channels* ```http POST /api/named_users/uninstall HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "named_user_id": ["user-id-1234","user-id-5678"] } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) response = NamedUser.uninstall( client=client, named_users=["user-id-1234", "user-id-5678"] ) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user_uninstall = UA::NamedUserUninstaller.new(client: airship) named_user_uninstall.named_user_ids = ['user-id-1234'] named_user_uninstall.uninstall ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserUninstallRequest namedUserUninstallRequest = NamedUserUninstallRequest .newUninstallRequest(ImmutableList.of("user-id-1234","user-id-5678")); Response response = client.execute(namedUserUninstallRequest); ``` --- ## Uninstall channels {#uninstallchannels} Uninstalls a channel, removing it and all accompanying analytic data (including Performance Analytics) from Airship systems in accordance with data privacy law compliance. Uninstallation is handled automatically by the Airship SDK and push systems. If a user decides to opt in to communications again (either by using your app or other user preferences), they will create a new channel and a new set of analytic data. The value of a Channel ID may be the same as before however none of the associated metadata will persist when a user opts in again. A new Channel ID will be created if the user clears their browser’s cookies and data, deletes and reinstalls the app, etc. See [Individual Data Privacy Rights Under Data Privacy Laws](/docs/guides/audience/privacy/individual-data-privacy/) for more information about data privacy law compliance. [Jump to examples ↓](#uninstallchannels-examples) ### `POST /api/channels/uninstall` {{< note >}} Channel uninstallation, like channel creation, is an asynchronous operation and may take some time to complete. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` Type: `array` **Responses** **`202`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/uninstall HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json [ { "channel_id": "b8f9b663-0a3b-cf45-587a-be880946e881", "device_type": "ios" }, { "channel_id": "13863b3c-f860-4bbf-a9f1-4d785379b8a2", "device_type": "android" } ] ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, ChannelUninstall ) client = BasicAuthClient( key='', secret='' ) channel_uninstall = ChannelUninstall(client) channel = { "channel_id": 'b8f9b663-0a3b-cf45-587a-be880946e881', "device_type": "ios" } channel_uninstall.uninstall(channel) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') cu = UA::ChannelUninstall.new(client: airship) chans = [{"channel_id" => "b8f9b663-0a3b-cf45-587a-be880946e881", "device_type" => "ios"}, {"channel_id" => "13863b3c-f860-4bbf-a9f1-4d785379b8a2", "device_type" => "android"}] cu.uninstall(channels: chans) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Set channels = ImmutableSet.of( new ChannelUninstallDevice("00f74677-4616-4958-bd91-30e949814d2c", ChannelUninstallDeviceType.IOS), new ChannelUninstallDevice("007f7156-9b82-4cb6-a2f9-e2c8e7fce13d", ChannelUninstallDeviceType.ANDROID) ); ChannelUninstallPayload payload = ChannelUninstallPayload.newBuilder() .setChannels(channels) .build(); ChannelUninstallRequest request = ChannelUninstallRequest.newRequest(payload); Response response = client.execute(request); ``` --- # Email > Register email channels, set opt-in status, and manipulate tags on email channels. ## Create email attachment {#createemailattachment} Create attachments by `POST`ing to the attachments URI. The body of the request must be a JSON object describing and including the contents of a file to attach. [Jump to examples ↓](#createemailattachment-examples) ### `POST /api/attachments` {{< important >}} * Attachments can be used for `transactional` sends only, not `commercial`. * Attachments cannot be used in Automations. * Attachment size is limited to 2.5 MB per attachment, with a 20 MB content size limit on each message, including content body and all attachments. * Attachment count is limited to 10 per email. * Sending attachments with malicious content is strictly prohibited. This is enforced in part by blocking file types with .bat and .exe extensions. * Attachments have a TTL (Time To Live) of 60 days. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): att **Request body** **Content-Type:** `application/json` - **`content_type`** `string` **REQUIRED** The mimetype of the uploaded file including the charset parameter, if needed. Example: `"text/plain; charset=\"UTF-8\""` Max length: 100 - **`data`** `string` **REQUIRED** Base64-encoded bytes of the file contents representing a maximum of 2.5 MiB of data when decoded. Padding with `=` chars is optional. - **`filename`** `string` **REQUIRED** The name of the uploaded file (max 255 UTF-8 bytes). Multiple files with the same name are allowed in separate requests. **Responses** **`201`** The email attachment was created. The response body will contain the IDs of the created attachments. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`attachment_id`** `array[string]` The attachment ID for a newly-created attachment. Reference this ID in the `attachments` list in the [Email overrides](/docs/developer/rest-api/ua/schemas/platform-overrides/#emailoverrideobject). - **`ok`** `boolean` Either `true` or `false`. Represents if the operation completed successfully or not. If false, other properties defined here will not necessarily be present. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** The application does not have the proper entitlement to create attachments. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example create email attachment* ```http POST /attachments HTTP/1.1 Authorization: Bearer Content-Type: application/json Accept: application/vnd.urbanairship+json; version=3 { "filename": "rickroll.png", "content_type": "text/plain; charset=\"UTF-8\"", "data": "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8..." } ``` ```http HTTP/1.1 201 Accepted Data-Attribute: attachment_id Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "attachment_ids": [ "b0c46a8d-b701-441b-9d6e-147c183b28ca" ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); EmailAttachmentRequest emailAttachmentRequest = EmailAttachmentRequest.newRequest() .setContentType("text/plain; charset=\"UTF-8\"") .setData("iBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8...") .setFilename("rickroll.png"); Response response = client.execute(emailAttachmentRequest); ``` ```python from urbanairship import ( BearerTokenClient, EmailAttachment ) client = BearerTokenClient( app_key='', token='' ) attachment = EmailAttachment( client=client, filename='rickroll.png', content_type='image/png; charset="UTF-8"', filepath='path/to/never_gonna.png' ) response = attachment.post() print(response.get('attachment_ids')) ``` --- ## Custom unsubscribe email channel {#customunsubscribeemailchannel} Opts-out an email address using a custom unsubscribe token. Requires [Custom Unsubscribe](/docs/developer/api-integrations/email/custom-unsubscribe-pages/) be enabled for your project. This endpoint is public and does not require authentication. [Jump to examples ↓](#customunsubscribeemailchannel-examples) ### `GET /api/channels/email/custom-unsubscribe` **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `ua_unsubscribe_token` | `string` | Required | The token for the unsubscribe request. | | `ua_redirect` | `string` | | URL of the page to redirect to after unsubscribe. A default confirmation page will be used if not provided. | **Responses** **`302`** The channel was successfully opted out and will be redirected to a confirmation page. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | URL of the page to redirect to after unsubscribe. | **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/channels/email/custom-unsubscribe?ua_redirect=https://example.com/success.html&ua_unsubscribe_token=eyJhcHBfa2V5IjoiVmwwd3lHOGtTeUN5T1VXOThXajR4ZyIsImNhbXBhaWducyI6W10sInB1c2hfaWQiOiJlY2U0MDliMC0yNzYyLTExZWUtYjE4Ny0wMjQyNDkzZjM2MTkiLCJtZXNzYWdlX3R5cGUiOiJjb21tZXJjaWFsIiwiY2hhbm5lbF9pZCI6Ik9IWWdxTDJfU3FHMTRQZWlfWjV2QkEifQ%3D%3D HTTP/1.1 Accept: */* ``` ```http HTTP/1.1 302 Found Location: https://example.com/success.html ``` --- ## Email tags {#modifyemailchanneltags} Add, remove, or set tags for a single email channel. [Jump to examples ↓](#modifyemailchanneltags-examples) ### `POST /api/channels/email/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per channel. Adding more than 1,000 tags per channel can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per channel, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** A single request body can contain an `add` and/or `remove` field or a single `set` field. One or more of the `add`, `remove`, or `set` keys must be present in the request. **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Adds the specified tags to the channel. Tags that are already present are not modified/removed as a result of this operation. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** Specifies the email address you want to perform tag operations against. Must contain a single `email_address` key. **OBJECT PROPERTIES** - **`email_address`** `string` **REQUIRED** The email address you want to modify tags for. Accepts a single string value representing an email address. Example: `name@example.com` - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Removes the specified tags from the channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Assigns a list of tags exactly. Any previously set tags that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** Returns OK for success. If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 will be returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/email/tags HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "email_address": "name@example.com" }, "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); EmailTagRequest request = EmailTagRequest.newRequest(); emailTagRequest.addEmailChannel("name@example.com") .addTags("my_fav_tag_group1", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("my_fav_tag_group2", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("my_fav_tag_group3", ImmutableSet.of("tag1", "tag2", "tag3")); Response response = client.execute(request); ``` ```python from urbanairship import ( BearerTokenClient, EmailTags ) client = BearerTokenClient( app_key='', token='' ) # replaces all existing tags on an email channel email_tags = EmailTags(airship=client, address='name@example.com') email_tags.set(group='my_tag_group', tags=['one', 'two', 'three']) email_tags.send() # adds and removes tags from an email channel email_tags = EmailTags(airship=client, address='name@example.com') email_tags.remove(group='my_tag_group', tags=['one', 'two', 'three']) email_tags.add(group='my_tag_group', tags=['some', 'new', 'tags']) email_tags.send() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_tags = UA::EmailTags.new(client: airship) #set an audience email_tags.set_audience(email_address: 'name@example.com') #add a tag email_tags.add(group_name: 'my_fav_tag_group1', tags: 'tag2') #remove a tag email_tags.remove(group_name: 'my_fav_tag_group1', tags: 'tag1') email_tags.send_request ``` --- ## Look up an email address {#getemailchannel} Returns a channel by email address. For security, email addresses are one-way hashed and aren't returned when you look up a channel by ID. Use this endpoint to find a channel belonging to a particular email address. You may need to escape the `@` character in URLs using`%40`. [Jump to examples ↓](#getemailchannel-examples) ### `GET /api/channels/email/{email}` {{< note >}} Emails with an `opted_out` date that is after or equal to the `opted_in` date will not be sent for that channel. A `commercial_opted_in` date is required for sending commercial emails. Transactional emails do not require a `transactional_opted_in`. This field is used in the case where a user has unsubscribed to transactional email and would like to reassert consent to receive transactional emails. The `opt_in` property is always set to true for an email channel, so it should be ignored. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `email` | `string` | Required | The email address of the channel you want to look up. | **Responses** **`200`** A channel exists for the email address Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`channel`** `object` <[Channel listing object]({{< ref "/developer/rest-api/ua/schemas/channels/" >}}#channellistingobject)> Describes a channel listing object. - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/channels/email/name%40example.com HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "channel": { "channel_id": "01234567-890a-bcde-f012-3456789abc0", "device_type": "email", "installed": true, "created": "2020-08-08T20:41:06", "named_user_id": "some_id_that_maps_to_your_systems", "email_address": "name@example.com", "tag_groups": { "tag_group_1": ["tag1", "tag2"], "tag_group_2": ["tag1", "tag2"] }, "address": null, "opt_in": true, "commercial_opted_in": "2020-10-28T10:34:22", "commercial_opted_out": "2020-06-03T09:15:00", "transactional_opted_in": "2020-10-28T10:34:22", "open_tracking_opted_in": "2022-12-11T00:00:00", "click_tracking_opted_in": "2022-12-11T00:00:00", "open_tracking_opted_out": "2022-12-12T00:00:00", "click_tracking_opted_out": "2022-12-12T00:00:00", "last_registration": "2020-05-01T18:00:27" } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ChannelRequest channelRequest = ChannelRequest.newEmailLookupRequest("name@example.com"); Response response = client.execute(channelRequest); ``` ```python from urbanairship import ( BearerTokenClient, Email ) client = BearerTokenClient( app_key='', token='' ) response = Email.lookup(airship=client, address='name@example.com') ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_channel = UA::Email.new(client: airship) email_channel.address = 'name@example.com' email_channel.lookup ``` --- ## Register email channel {#registeremailchannel} Create a new email channel or update an existing channel. If you provide the email address of an existing channel, the call is treated as a PUT. To update the address of an existing channel, see the [Replace Email Channel](/docs/developer/rest-api/ua/operations/email/#replaceemailchannel) endpoint. [Jump to examples ↓](#registeremailchannel-examples) ### `POST /api/channels/email` {{< note >}} Channel creation is asynchronous, so when associating a newly created channel, both a Channel ID and a device type are required to prevent "channel does not exist" errors. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** A single email channel object. **Content-Type:** `application/json` - **`attributes`** `object` An optional object containing the customer-provided attributes associated with the email. - **`channel`** `object` **REQUIRED** **OBJECT PROPERTIES** - **`address`** `string` **REQUIRED** The email address being registered. Example: `name@example.com` - **`click_tracking_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user opted in to click tracking. Format: `date-time` - **`click_tracking_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user opted out of click tracking. Format: `date-time` - **`commercial_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive commercial emails. Format: `date-time` - **`commercial_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user explicitly denied permission to receive commercial emails. Format: `date-time` - **`locale_country`** `string` The device property tag related to locale country setting. Example: `US` - **`locale_language`** `string` The device property tag related to locale language setting. Example: `en` - **`open_tracking_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user opted in to open tracking. Format: `date-time` - **`open_tracking_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user opted out of open tracking. Format: `date-time` - **`suppression_state`** `string` If an email channel is suppressed, the reason for its suppression. Email channels with any suppression state set will not have any delivery to them fulfilled. If a more specific reason is not known, use `imported`. Possible values: `spam_complaint`, `commercial_spam_complaint`, `bounce`, `imported` - **`timezone`** `string` The device property tag related to time zone setting. Example: `America/Los_Angeles` - **`transactional_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive transactional emails. Users do not need to opt-in to receive transactional emails unless they have previously opted out. Format: `date-time` - **`transactional_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user explicitly denied permission to receive transactional emails. Format: `date-time` - **`type`** `string` **REQUIRED** The type of channel you are registering. Possible values: `email` Example: `email` - **`opt_in_mode`** `string` The opt-in mode for registering the channel. `classic` is the default when unspecified, `double` creates a `double_opt_in` event. Possible values: `classic`, `double` Example: `double` - **`properties`** `object` An object containing event properties. You can use these properties to filter the double opt-in event and reference them in your message content by using handlebars. Items in the `properties` object are limited to a 255-character maximum string length. Example: `[object Object]` - **`tag_operations`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Optionally one or more tag group objects associated with the email. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** An existing email channel was found matching the address and was updated. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`attributes`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the attributes were set correctly. - **`channel_id`** `string` A unique string identifying the email channel. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`ok`** `boolean` **REQUIRED** If `true`, the operation was successful. If `false`, other properties defined here will not necessarily be present. - **`tags`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the tags were set correctly. **`201`** The email channel was created. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The newly created email channel. | Response body: **Content-Type:** `text/plain` - **`channel_id`** `string` A unique string identifying the email channel. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`ok`** `boolean` **REQUIRED** Either `true` or `false`. Represents if the operation completed successfully or not. If false, other properties defined here will not necessarily be present. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/email HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel" : { "type": "email", "commercial_opted_in": "2020-10-28T10:34:22", "open_tracking_opted_in": "2022-12-11T00:00:00", "click_tracking_opted_in": "2022-12-11T00:00:00", "address": "name@example.com", "timezone" : "America/Los_Angeles", "locale_country" : "US", "locale_language" : "en" }, "opt_in_mode" : "classic", "properties" : { "interests" : "newsletter" }, "tag_operations": { "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } }, "attributes": { "my_fav_attribute1": "attribute1", "my_fav_attribute2": "attribute2" } } ``` ```http HTTP/1.1 201 Created Location: https://go.urbanairship.com/api/channels/251d3318-b3cb-4e9f-876a-ea3bfa6e47bd Content-Type: application/json { "ok": true, "channel_id": "251d3318-b3cb-4e9f-876a-ea3bfa6e47bd", "attributes": {"ok": true}, "tags": {"ok": true} } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); RegisterEmailChannel emailChannel = RegisterEmailChannel.newBuilder() .setAddress("name@example.com") .setEmailOptInLevel(OptInLevel.EMAIL_COMMERCIAL_OPTED_IN, "2020-10-28T10:34:22") .setEmailOptInMode(OptInMode.CLASSIC) .addProperty("interests","newletter") .build(); RegisterEmailChannelRequest request = RegisterEmailChannelRequest.newRequest(emailChannel); Response response = client.execute(request); ``` ```python from urbanairship import ( BearerTokenClient, Email ) client = BearerTokenClient( app_key='', token='' ) email = Email( client=client, address='name@example.com', commercial_opted_in='2020-10-28T10:34:22', timezone='America/Los_Angeles', locale_country='US', locale_language='en' ) response = email.register() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_channel = UA::Email.new(client: airship) email_channel.type = 'email' email_channel.commercial_opted_in = '2020-10-28T10:34:22' email_channel.address = 'name@example.com' email_channel.timezone = 'America/Los_Angeles' email_channel.locale_country = 'US' email_channel.locale_language = 'en' email_channel.register ``` --- ## Remove suppression from an email channel {#unsuppressemailchannel} Remove the suppression reason for an existing email channel, allowing the channel to receive emails, depending on the channel's commercial and transactional opt-in status. [Jump to examples ↓](#unsuppressemailchannel-examples) ### `POST /api/channels/email/unsuppress` {{< important >}} Calling this endpoint will not modify commercial or transactional opt-in status to opted-in. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`address`** `string` **REQUIRED** The email address for the channel to be unsuppressed. Example: `user@example.com` **Responses** **`202`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/email/unsuppress HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "address": "name@example.com" } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); UnsuppressEmailChannelRequest request = UnsuppressEmailChannelRequest.newRequest("name@example.com"); Response response = client.execute(request); ``` --- ## Replace email channel {#replaceemailchannel} Creates a new email channel in place of the provided channel. You may use this endpoint to change a contact's email address. When called with an email channel, this endpoint will: * Register a new channel * Associate the new email channel with the same user as the source channel * Uninstall the source channel [Jump to examples ↓](#replaceemailchannel-examples) ### `POST /api/channels/email/replace/{channel_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `channel_id` | `string` | Required | The email `channel_id` you want to modify. | **Request body** A single email channel object. **Content-Type:** `application/json` - **`attributes`** `object` An optional object containing the customer-provided attributes associated with the email. - **`channel`** `object` **REQUIRED** **OBJECT PROPERTIES** - **`address`** `string` **REQUIRED** The email address being registered. Example: `name@example.com` - **`click_tracking_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user opted in to click tracking. Format: `date-time` - **`click_tracking_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user opted out of click tracking. Format: `date-time` - **`commercial_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive commercial emails. Format: `date-time` - **`commercial_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user explicitly denied permission to receive commercial emails. Format: `date-time` - **`locale_country`** `string` The device property tag related to locale country setting. Example: `US` - **`locale_language`** `string` The device property tag related to locale language setting. Example: `en` - **`open_tracking_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user opted in to open tracking. Format: `date-time` - **`open_tracking_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user opted out of open tracking. Format: `date-time` - **`suppression_state`** `string` If an email channel is suppressed, the reason for its suppression. Email channels with any suppression state set will not have any delivery to them fulfilled. If a more specific reason is not known, use `imported`. Possible values: `spam_complaint`, `commercial_spam_complaint`, `bounce`, `imported` - **`timezone`** `string` The device property tag related to time zone setting. Example: `America/Los_Angeles` - **`transactional_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive transactional emails. Users do not need to opt-in to receive transactional emails unless they have previously opted out. Format: `date-time` - **`transactional_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user explicitly denied permission to receive transactional emails. Format: `date-time` - **`type`** `string` **REQUIRED** The type of channel you are registering. Possible values: `email` Example: `email` - **`opt_in_mode`** `string` The opt-in mode for registering the channel. `classic` is the default when unspecified, `double` creates a `double_opt_in` event. Possible values: `classic`, `double` Example: `double` - **`properties`** `object` An object containing event properties. You can use these properties to filter the double opt-in event and reference them in your message content by using handlebars. Items in the `properties` object are limited to a 255-character maximum string length. Example: `[object Object]` - **`tag_operations`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Optionally one or more tag group objects associated with the email. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`201`** The operation was successful. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The newly created email channel. | Response body: **Content-Type:** `text/plain` - **`channel_id`** `string` A unique string identifying the email channel. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`ok`** `boolean` Either `true` or `false`. Represents if the operation completed successfully or not. If false, other properties defined here will not necessarily be present. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/email/replace/9c36e8c7-5a73-47c0-9716-99fd3d4197d5 HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel" : { "type": "email", "commercial_opted_in": "2022-02-13T11:58:59", "address": "name@example.com", "timezone" : "America/Los_Angeles", "locale_country" : "US", "locale_language" : "en" } } ``` ```http HTTP/1.1 201 Created Content-Type: application/json Location: https://go.urbanairship.com/api/channels/251d3318-b3cb-4e9f-876a-ea3bfa6e47bd { "ok": true, "channel_id": "251d3318-b3cb-4e9f-876a-ea3bfa6e47bd" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); RegisterEmailChannel emailChannel = RegisterEmailChannel.newBuilder() .setAddress("name@example.com") .setEmailOptInLevel(OptInLevel.EMAIL_COMMERCIAL_OPTED_IN, "2022-02-13T11:58:59") .setTimeZone("America/Los_Angeles") .setLocaleCountry("US") .setLocaleLanguage("en") .build(); ReplaceEmailChannelRequest request = ReplaceEmailChannelRequest.newRequest("9c36e8c7-5a73-47c0-9716-99fd3d4197d5", emailChannel); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_channel = UA::Email.new(client: airship) email_channel.channel_id = '251d3318-b3cb-4e9f-876a-ea3bfa6e47bd' email_channel.address = 'tommy@example.com' email_channel.type = 'email' email_channel.commercial_opted_in = '2020-10-28T10:34:22' email_channel.replace ``` --- ## Suppress an email channel {#suppressemailchannel} Suppress an existing email channel, disallowing any future delivery from being fulfilled for the channel. [Jump to examples ↓](#suppressemailchannel-examples) ### `POST /api/channels/email/suppress` {{< note >}} Suppression state types that only apply to commercial messages, such as `commercial_spam_complaint`, cannot overwrite suppression state types that also apply to transactional messages. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`address`** `string` **REQUIRED** The email address for the channel to be suppressed. Example: `user@example.com` - **`reason`** `string` **REQUIRED** The reason for suppressing the channel. If there is no specific reason, use `imported`. Possible values: `spam_complaint`, `commercial_spam_complaint`, `bounce`, `imported` Example: `spam_complaint` **Responses** **`202`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/email/suppress HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "address": "name@example.com", "reason": "spam_complaint" } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SuppressEmailChannelRequest request = SuppressEmailChannelRequest.newRequest("name@example.com","reason"); Response response = client.execute(request); ``` --- ## Uninstall email channel {#uninstallemailchannel} **Removes an email address from Airship. Use with caution.** If the uninstalled email address opts-in again, it might generate a new channel_id. If a user generates a new `channel_id` when they opt-in again, the new `channel_id` cannot be reassociated with any opt-in information, tags, Named Users, Performance Analytics reports, or other information from the that belonged to the previously-uninstalled email channel. [Jump to examples ↓](#uninstallemailchannel-examples) ### `POST /api/channels/email/uninstall` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** An email address of the channel to uninstall. **Content-Type:** `application/json` - **`email_address`** `string` **REQUIRED** The email address of the channel to uninstall. Example: `name@example.com` **Responses** **`202`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/email/uninstall HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "email_address": "name@example.com" } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); UninstallEmailChannel uninstallEmailChannel = UninstallEmailChannel.newBuilder() .setEmailAddress("name@example.com") .build(); UninstallEmailChannelRequest request = UninstallEmailChannelRequest.newRequest(uninstallEmailChannel); Response response = client.execute(request); ``` ```python from urbanairship import ( BearerTokenClient, Email ) client = BearerTokenClient( app_key='', token='' ) email = Email(airship=client, address='name@example.com') resp = email.uninstall() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_channel = UA::Email.new(client: airship) email_channel.address = 'name@example.com' email_channel.uninstall ``` --- ## Update an email channel {#updateemailchannel} Update an email channel. You can use this endpoint to update the subscription/unsubscription values. [Jump to examples ↓](#updateemailchannel-examples) ### `PUT /api/channels/email/{email}` {{< important >}} If you provide an `address` in this request, it must be the one that is associated with the channel you are updating. You may not update the user's email address with this endpoint. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `email` | `string` | Required | The email `channel_id` you want to modify. | **Request body** **Content-Type:** `application/json` - **`channel`** `object` **REQUIRED** **OBJECT PROPERTIES** - **`address`** `string` The email address associated with the email channel. If provided, it must match the existing email address or the request will be rejected with a 400 status code. Example: `tommy@example.com` - **`commercial_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive commercial emails. Format: `date-time` - **`commercial_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user explicitly denied permission to receive commercial emails. Format: `date-time` - **`device_type`** `string` The type of channel you are updating. Possible values: `email` Example: `email` - **`locale_country`** `string` The device property tag related to locale country setting. Example: `US` - **`locale_language`** `string` The device property tag related to locale language setting. Example: `en` - **`suppression_state`** `string` If an email channel is suppressed, the reason for its suppression. Email channels with any suppression state set will not have any delivery to them fulfilled. If a more specific reason is not known, use `imported`. Possible values: `spam_complaint`, `commercial_spam_complaint`, `bounce`, `imported` - **`timezone`** `string` The device property tag related to time zone setting. Example: `America/Los_Angeles` - **`transactional_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive transactional emails. Users do not need to opt-in to receive transactional emails unless they have previously opted out. Format: `date-time` - **`transactional_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user explicitly denied permission to receive transactional emails. Format: `date-time` **Responses** **`200`** The email channel was updated. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The updated email channel. | Response body: **Content-Type:** `text/plain` - **`channel_id`** `string` A unique string identifying the email channel. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`ok`** `boolean` Either `true` or `false`. Represents if the operation completed successfully or not. If false, other properties defined here will not necessarily be present. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example update email address* ```http PUT /api/channels/email/251d3318-b3cb-4e9f-876a-ea3bfa6e47bd HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel" : { "device_type": "email", "address": "tommy@example.com", "commercial_opted_in": "2020-10-28T10:34:22" } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 Location: https://go.urbanairship.com/api/channels/251d3318-b3cb-4e9f-876a-ea3bfa6e47bd { "ok": true, "channel_id": "251d3318-b3cb-4e9f-876a-ea3bfa6e47bd" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); UpdateEmailChannel updateEmailChannel = UpdateEmailChannel.newBuilder() .setAddress("name@example.com") .setEmailOptInLevel(OptInLevel.EMAIL_COMMERCIAL_OPTED_IN, "2021-10-28T10:34:22") .setEmailOptInLevel(OptInLevel.EMAIL_TRANSACTIONAL_OPTED_IN,"2021-10-28T10:34:22") .build(); UpdateEmailChannelRequest updateEmailChannelRequest = UpdateEmailChannelRequest.newRequest("6c8f1d3a-64d8-4ef9-b7a1-9b128013327e", updateEmailChannel); Response response = client.execute(updateEmailChannelRequest); ``` ```python from urbanairship import ( BearerTokenClient, Email ) client = BearerTokenClient( app_key='', token='' ) email = Email( client=client, address='tommy@example.com', commercial_opted_in='2020-10-28T10:34:22' ) response = email.update(channel_id='251d3318-b3cb-4e9f-876a-ea3bfa6e47bd') ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_channel = UA::Email.new(client: airship) email_channel.channel_id = '251d3318-b3cb-4e9f-876a-ea3bfa6e47bd' email_channel.type = 'email' email_channel.commercial_opted_in = '2020-10-28T10:34:22' email_channel.update ``` --- # Named Users > A Named User is a proprietary identifier that maps customer-chosen IDs, e.g., CRM data, to Channels. It is useful to think of a Named User as an individual consumer who might have more than one mobile device registered with your app. For example, Named User "john_doe_123" might have a personal Android phone and an iPad, on both of which he has opted in for push notifications. If you want to reach John on both devices, associate the Channel (device) identifiers for each device to the Named User "john_doe_123," and push to the Named User. Notifications will then fan out to each associated device. ## Named User listing or lookup {#getnameduser} Return a list of Named Users or look up a single Named User by `named_user_id`. [Jump to examples ↓](#getnameduser-examples) ### `GET /api/named_users` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `id` | `string` | | The `named_user_id` you want to look up. When querying a `named_user_id`, the response contains a single `named_user` object. If you do not query a specific `named_user_id`, the response returns an array of `named_users`, in which each object represents an individual Named User. | **Responses** **`200`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` **One of:** - **`named_user`** `object` <[Named User object]({{< ref "/developer/rest-api/ua/schemas/named-user/" >}}#nameduserresponsebody)> The response body for a Named User listing, including tags, channels and attributes associated with the Named User. - **`ok`** `boolean` **REQUIRED** Success. - **`named_users`** `array` <[Named User object]({{< ref "/developer/rest-api/ua/schemas/named-user/" >}}#nameduserresponsebody)> - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next page of results. Format: `url` Example: `https://go.urbanairship.com/api/named_users?start=john_doe` - **`ok`** `boolean` **REQUIRED** Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example Named User lookup* ```http GET /api/named_users/?id=user-456 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "named_user": { "named_user_id": "user-456", "created" : "2020-04-08T20:41:06", "last_modified" : "2020-05-01T18:00:27", "tags": { "my_fav_tag_group": [ "tag1", "tag2" ] }, "subscription_lists": [ { "list_ids": ["example_listId-1", "example_listId-5"], "scope": "web" }, { "list_ids": ["example_listId-2", "example_listId-3"], "scope": "app" }, { "list_ids": ["example_listId-2"], "scope": "web" }, { "list_ids": ["example_listId-3"], "scope": "email" }, { "list_ids": ["example_listId-4"], "scope": "sms" } ], "attributes": { "item_purchased": "Fur removal tool", "cats_name": "Sammy", "pets_age": 12 }, "user_attributes": { "ua_country": "US", "ua_language": "en", "ua_tz": "America/Los_Angeles" }, "channels": [ { "channel_id": "dceafd02-b852-4305-83df-98b65fa40dd4", "device_type": "ios", "installed": true, "opt_in": true, "push_address": "FFFF", "created": "2020-04-08T20:41:06", "last_registration": "2020-05-01T18:00:27", "tags": [ "meow" ] } ] } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserListingRequest request = NamedUserListingRequest.newRequest("user-456"); Response response = client.execute(request); NamedUserView namedUser = response.getBody().get().getNamedUserView().get(); // The Named User ID String namedUserId = namedUser.getNamedUserId(); // Map of tag groups and the associated sets of tags ImmutableMap> namedUserTags = namedUser.getNamedUserTags(); // All channel objects associated with the Named User ImmutableSet channelViews = namedUser.getChannelViews(); ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) named_user = NamedUser(airship=client, named_user_id='user-456') response = named_user.lookup() print(response) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user = UA::NamedUser.new(client: airship) named_user.named_user_id = 'user-456' user = named_user.lookup ``` *Example Named User listing* ```http GET /api/named_users HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: named_users Link: ; rel=next Content-Type: application/vnd.urbanairship+json; version=3 { "next_page": "https://go.urbanairship.com/api/named_users?start=user-1234", "named_users": [ { "named_user_id": "user-id-1234", "created" : "2020-04-08T20:41:06", "last_modified" : "2020-05-01T18:00:27", "tags": { "my_fav_tag_group": ["tag1", "tag2"] }, "subscription_lists": [ { "list_ids": ["example_listId-1", "example_listId-5"], "scope": "web" }, { "list_ids": ["example_listId-2", "example_listId-3"], "scope": "app" }, { "list_ids": ["example_listId-2"], "scope": "web" }, { "list_ids": ["example_listId-3"], "scope": "email" } ], "attributes":{ "item_purchased":"Fur removal tool", "cats_name":"fluffy butt", "pets_age":2 }, "user_attributes": { "ua_country": "US", "ua_language": "en", "ua_tz": "America/Los_Angeles" }, "channels": [ { "channel_id": "dceafd02-b852-4305-83df-98b65fa40dd5", "device_type": "ios", "installed": true, "opt_in": true, "push_address": "FFFF", "created": "2020-04-08T20:41:06", "last_registration": "2020-05-01T18:00:27", "alias": "xxxx", "tags": ["asdf"], "ios": { "badge": 0, "quiettime": { "start": "22:00", "end": "06:00" }, "tz": "America/Los_Angeles" } } ] } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserListingRequest request = NamedUserListingRequest.newRequest(); Response response = client.execute(request); ImmutableList namedUsers = response.getBody().get().getNamedUserViews().get(); ``` ```python from urbanairship import ( BasicAuthClient, NamedUserList ) client = BasicAuthClient( key='', secret='' ) named_user_list = NamedUserList(airship=client) for n in named_user_list: print(n.named_user_id) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user_list = UA::NamedUserList.new(client: airship) named_user_list.each do |named_user| puts(named_user) end ``` --- ## Named User update {#updatenameduser} Create or update a Named User by associating/disassociating channels and adding/removing tags and attributes in a single request. [Jump to examples ↓](#updatenameduser-examples) ### `POST /api/named_users/{named_user_id}` {{< warning >}} If a channel has an assigned Named User and you make an additional call to associate that same channel with a new Named User, the original Named User association will be removed and the new Named User and associated data will take its place. Additionally, all tags associated to the original Named User cannot be used to address this channel unless they are also associated with the new Named User. {{< /warning >}} {{< important >}} We support up to 1,000 tags per Named User. Adding more than 1,000 tags per Named User can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per Named User, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `named_user_id` | `string` | Required | A string value identifying the user, without leading or trailing whitespace. If this value contains reserved or special characters they must be URL encoded. | **Request body** **Content-Type:** `application/json` [Named User update payload]({{< ref "/developer/rest-api/ua/schemas/named-user/" >}}#nameduserupdate) **Responses** **`200`** Request was accepted. Response body: **Content-Type:** `application/json` - **`attribute_warnings`** `string` Warnings encountered when processing attributes for this Named User. - **`ok`** `boolean` **REQUIRED** Set to `true` when status code is `200`. - **`tag_warnings`** `string` Warnings encountered when processing tags for this Named User. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Create a Named User by associating an email and SMS channel and setting tags and attributes. * ```http POST /api/named_users/john_doe HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "associate": [ { "email_address": "john@example.com" }, { "channel_id": "f5346fa3-99f1-496d-be37-2895ef58f5a5", "device_type": "sms" } ], "tags": { "set": { "subscription_status": ["gold"], "favorites" : ["sports", "stocks"] } }, "attributes": [ { "action": "set", "key": "name", "value": "John" } ] } ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) associate = [ {"email_address": "john@example.com"}, {"channel_id": "f5346fa3-99f1-496d-be37-2895ef58f5a5", "device_type": "sms"} ] tags = { "set": { "subscription_status": ["gold"], "favorites" : ["sports", "stocks"] } } attributes = [ { "action": "set", "key": "name", "value": "John" } ] named_user = NamedUser( airship=client, named_user_id="john_doe" ) response = named_user.update( associate=associate, tags=tags, attributes=attributes ) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserUpdateChannel namedUserUpdateChannel = NamedUserUpdateChannel.newBuilder() .addChannel(NamedUserUpdateDeviceType.ANDROID_CHANNEL, "aa2ae18c-f4b0-48ac-a859-55f26d2a7439") .build(); Attribute lastName = Attribute.newBuilder() .setAction(AttributeAction.SET) .setKey("pseudo") .setValue("Pataki") .build(); NamedUserUpdatePayload namedUserUpdatePayload = NamedUserUpdatePayload.newBuilder() .addAttribute(lastName) .addTags("go", List.of("test1","test2")) .removeTags("go",List.of("test3","test4")) .addNamedUserUpdateChannel(namedUserUpdateChannel) .setAction(NamedUserUpdateChannelAction.ASSOCIATE) .build(); NamedUserUpdateRequest request = NamedUserUpdateRequest.newRequest("john", namedUserUpdatePayload); Response response = client.execute(request); ``` --- ## Named Users association {#associatenameduser} Associate a channel or email address with a Named User (`named_user_id`). If the `named_user_id` does not already exist, this operation will create it. If the `channel_id` or `email address` is already associated with the `named_user_id`, this operation will do nothing. [Jump to examples ↓](#associatenameduser-examples) ### `POST /api/named_users/associate` {{< warning >}} If a channel has an assigned Named User and you make an additional call to associate that same channel with a new Named User, the original Named User association will be removed and the new Named User and associated data will take its place. Additionally, all tags associated to the original Named User cannot be used to address this channel unless they are also associated with the new Named User. {{< /warning >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Request body** Named User association requires a `channel_id` or `email_address`. Do not provide both in the same request. You can associate up to 100 Channel IDs to a Named User. Channel creation is asynchronous, so when associating a newly created channel, both a Channel ID and a device type are required to prevent "channel does not exist" errors. **Content-Type:** `application/json` **One of:** - **`channel_id`** `string` **REQUIRED** The Channel ID you want to associate with a Named User. Format: `uuid` Example: `9c36e8c7-5a73-47c0-9716-99fd3d4197d5` - **`device_type`** `string` The device type of the channel. Possible values: `ios`, `android`, `amazon`, `web`, `open`, `email`, `sms` - **`named_user_id`** `string` **REQUIRED** A string value identifying the user, without leading or trailing whitespace. Min length: 1, Max length: 128 Example: `john_doe` - **`email_address`** `string` **REQUIRED** The email address you want to associate with a Named User. Format: `email` Example: `user@example.com` - **`named_user_id`** `string` **REQUIRED** The existing Named User ID Min length: 1, Max length: 128 Example: `john_doe` **Responses** **`200`** The request was accepted but is not guaranteed to be successfully processed. If the Named User has more than 1,000 channels associated with it, the request will be ignored. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example associate an iOS channel with a Named User* ```http POST /api/named_users/associate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel_id": "df6a6b50-9843-0304-d5a5-743f246a4946", "device_type": "ios", "named_user_id": "user-id-1234" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserRequest request = NamedUserRequest.newAssociationRequest() .setChannel("df6a6b50-9843-0304-d5a5-743f246a4946", ChannelType.IOS) .setNamedUserId("user-id-1234"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) named_user = NamedUser(airship=client, named_user_id='user-id-1234') response = named_user.associate(channel_id='df6a6b50-9843-0304-d5a5-743f246a4946', device_type='ios') ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user = UA::NamedUser.new(client: airship) named_user.named_user_id = 'user-id-1234' named_user.associate(channel_id: 'df6a6b50-9843-0304-d5a5-743f246a4946', device_type: 'ios') ``` *Example associate a web channel with Named User (do not declare device type)* ```http POST /api/named_users/associate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel_id": "wf6a6b50-9843-0304-d5a5-743f246a4946", "named_user_id": "user-id-1234" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserRequest request = NamedUserRequest.newAssociationRequest() .setChannel("wf6a6b50-9843-0304-d5a5-743f246a4946", ChannelType.WEB) .setNamedUserId("user-id-1234"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) named_user = NamedUser(airship=client, named_user_id='user-id-1234') response = named_user.associate(channel_id='wf6a6b50-9843-0304-d5a5-743f246a4946') ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user = UA::NamedUser.new(client: airship) named_user.named_user_id = 'user-id-1234' named_user.associate(channel_id: 'wf6a6b50-9843-0304-d5a5-743f246a4946') ``` *Example associate an email channel with Named User* ```http POST /api/named_users/associate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "email_address": "monopoly.man@example.com", "named_user_id": "user-id-1234" } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) named_user = NamedUser(airship=client, named_user_id='user-id-1234') response = named_user.email_associate(email_address='monopoly.man@example.com') ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserRequest request = NamedUserRequest.newAssociationRequest() .setChannel("em6a6b50-9843-0304-d5a5-743f246a4946", ChannelType.EMAIL) .setNamedUserId("user-id-1234"); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user = UA::NamedUser.new(client: airship) named_user.named_user_id = 'user-id-1234' named_user.associate(channel_id: 'em6a6b50-9843-0304-d5a5-743f246a4946') ``` --- ## Named Users disassociation {#disassociatednameduser} Disassociate a channel or an email address from a `named_user_id`. [Jump to examples ↓](#disassociatednameduser-examples) ### `POST /api/named_users/disassociate` **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Request body** **Content-Type:** `application/json` **One of:** - **`channel_id`** `string` **REQUIRED** The Channel ID you want to disassociate from a Named User. Format: `uuid` Example: `9c36e8c7-5a73-47c0-9716-99fd3d4197d5` - **`device_type`** `string` The device type of the channel. Possible values: `ios`, `android`, `amazon`, `web`, `email`, `sms`, `open` - **`named_user_id`** `string` The existing Named User ID. Min length: 1, Max length: 128 Example: `john_doe` - **`email_address`** `string` **REQUIRED** The email address you want to disassociate from a Named User. Format: `email` Example: `user@example.com` - **`named_user_id`** `string` A string value identifying the new user with no leading or trailing whitespace. If the `named_user_id` does not already exist, this operation will create a new Named User and associate the `channel_id` with it. Min length: 1, Max length: 128 Example: `john_doe` **Responses** **`200`** The request was accepted but is not guaranteed to be successfully processed. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/named_users/disassociate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel_id": "df6a6b50-9843-0304-d5a5-743f246a4946", "device_type": "ios", "named_user_id": "user-id-1234" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserRequest request = NamedUserRequest.newDisassociationRequest() .setChannel("df6a6b50-9843-0304-d5a5-743f246a4946", ChannelType.IOS); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user = UA::NamedUser.new(client: airship) named_user.disassociate(channel_id: 'df6a6b50-9843-0304-d5a5-743f246a4946', device_type: 'ios') ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) named_user = NamedUser(airship=client, named_user_id='user-id-1234') response = named_user.disassociate(channel_id='df6a6b50-9843-0304-d5a5-743f246a4946', device_type='ios') ``` *Example disassociate an email channel from Named User* ```http POST /api/named_users/disassociate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "email_address": "monopoly.man@example.com", "named_user_id": "user-id-1234" } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) named_user = NamedUser(airship=client, named_user_id='user-id-1234') response = named_user.email_disassociate(email_address='monopoly.man@example.com') ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserRequest request = NamedUserRequest.newDisassociationRequest() .setChannel("em6a6b50-9843-0304-d5a5-743f246a4946", ChannelType.EMAIL) .setNamedUserId("user-id-1234"); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user = UA::NamedUser.new(client: airship) named_user.disassociate(channel_id: 'em6a6b50-9843-0304-d5a5-743f246a4946') ``` --- ## Named Users tags {#modifynamedusertags} Add, remove, or set tags on a Named User. A single request body may contain add and/or remove objects or a single set field. At least one of the add, remove, or set objects must be present in a request. [Jump to examples ↓](#modifynamedusertags-examples) ### `POST /api/named_users/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per Named User. Adding more than 1,000 tags per Named User can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per Named User, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Request body** **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Add the list of tags to the Named User(s), but do not remove any. If the tags are already present, they are not modified. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** The Named User(s) you want to associate/disassociate tags with. **OBJECT PROPERTIES** - **`named_user_id`** `array[string]` Min items: 1, Max items: 1000 - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Remove the list of tags from the Named User(s), but do not remove any others. If the tags are not currently present, nothing happens. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Set these tags for the audience; any tags previously associated with the audience tags that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 will be returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` **REQUIRED** Set to `true` when status code is `200`. - **`tag_warnings`** `string` Warnings encountered when processing tags for this Named User. **`400`** Parsing or validating the request failed. You will see this error if the same tag is present in both the add and remove fields. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/named_users/tags HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "named_user_id": [ "user-1", "user-2", "user-3" ] }, "add": { "crm": [ "tag1", "tag2", "tag3" ], "loyalty": [ "tag1", "tag4", "tag5" ] }, "remove": { "loyalty": [ "tag6", "tag7" ] } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserTagRequest request = NamedUserTagRequest.newRequest() .addNamedUsers("user-1", "user-2", "user-3") .addTags("crm", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("loyalty", ImmutableSet.of("tag1", "tag4", "tag5")) .removeTags("loyalty", ImmutableSet.of("tag6", "tag7")); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) named_user = NamedUser(airship=client, named_user_id='user-1') resp1 = named_user.tag( group='loyalty', add=['tag2', 'tag3', 'tag4'], remove='tag1' ) resp2 = named_user.tag( group='crm', set=['tag5', 'tag6'] ) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user_tags = UA::NamedUserTags.new(client: airship) named_user_ids = ['user-1', 'user-2', 'user-3'] named_user_tags.set_audience(user_ids: named_user_ids) named_user_tags.add(group_name: 'crm', tags: ['tag1', 'tag2', 'tag3']) named_user_tags.remove(group_name: 'loyalty', tags: ['tag6', 'tag7']) named_user_tags.send_request ``` --- ## Named Users uninstall {#uninstallnameduser} Disassociate and delete all channels associated with the named_user_id(s) and also delete the named_user_id(s). This call removes all channels associated with a Named User from Airship systems in compliance with data privacy laws. Uninstalling channels also removes accompanying analytic data (including Performance Analytics) from the system. See [Individual Data Privacy Rights Under Data Privacy Laws](/docs/guides/audience/privacy/individual-data-privacy/) for more information about data privacy law compliance. [Jump to examples ↓](#uninstallnameduser-examples) ### `POST /api/named_users/uninstall` {{< note >}} Channel uninstallation, like channel creation, is an asynchronous operation and may take some time to complete. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Request body** **Content-Type:** `application/json` - **`named_user_id`** `array[string]` **REQUIRED** Array of strings representing the named_user_id(s) you wish to be uninstalled. Must have between 1 to 100 items in the array with a 128 character/byte maximum per item. Min items: 1, Max items: 100 **Responses** **`200`** All channels have been deleted and disassociated from the Named User. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example delete all users and their associated channels* ```http POST /api/named_users/uninstall HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "named_user_id": ["user-id-1234","user-id-5678"] } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) response = NamedUser.uninstall( client=client, named_users=["user-id-1234", "user-id-5678"] ) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user_uninstall = UA::NamedUserUninstaller.new(client: airship) named_user_uninstall.named_user_ids = ['user-id-1234'] named_user_uninstall.uninstall ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserUninstallRequest namedUserUninstallRequest = NamedUserUninstallRequest .newUninstallRequest(ImmutableList.of("user-id-1234","user-id-5678")); Response response = client.execute(namedUserUninstallRequest); ``` --- ## Scoped Named User batch operations {#performnameduserscopedbatchoperations} Supports multiple operations on a Named User within a single request for a specified `scope`. The supported operation is `subscription_lists`. The behavior of each of these operations are the same as their individual request counterpart. [Jump to examples ↓](#performnameduserscopedbatchoperations-examples) ### `POST /api/named_users/scoped/{named_user_id}` {{< note >}} If you are using a single-channel Preference Center created before October 10, 2022, that has not been [migrated to user-level](/docs/guides/messaging/features/preference-centers/#migrating-to-a-user-level-preference-center), use the [`/api/channels/subscription_lists` endpoint](/docs/developer/rest-api/ua/operations/channels/#modifychannelsubscriptions) to add or remove individual channels to/from your subscription list. {{< /note >}} {{< important >}} The path parameter `named_user_id` should be URL-encoded to ensure it is handled correctly. Requirements of `named_user_id` can be found [here](#operation-api-named_users-associate-post-associate-channel_id-with-named-user-named_user_id). {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `named_user_id` | `string` | Required | A string value identifying the user, without leading or trailing whitespace. If this value contains reserved or special characters they must be URL encoded. | **Request body** **Content-Type:** `application/json` - **`scoped`** `array` <[Named User scoped batch item]({{< ref "/developer/rest-api/ua/schemas/subscription-lists/" >}}#scopedbatchitem)> An array of scopes and subscription lists. **Responses** **`200`** The scoped Named User batch operations succeeded. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example scoped Named User batch operations * ```http POST /api/named_users/scoped/b8f9b663-0a3b-cf45-587a-be880946e881 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "scoped": [ { "scope": ["app"], "subscription_lists": { "subscribe": ["stickers", "gifs"], "unsubscribe": ["cookies"] } }, { "scope": ["web"], "subscription_lists": { "subscribe": ["daily_snacks", "brunch"], "unsubscribe": ["promotions"] } } ] } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Set scopeTypes1 = new HashSet<>(Arrays.asList(NamedUserScopeType.APP)); Set subscribeLists1 = new HashSet<>(Arrays.asList("stickers", "gifs")); Set unsubscribeLists1 = new HashSet<>(Arrays.asList("cookies")); Set scopeTypes2 = new HashSet<>(Arrays.asList(NamedUserScopeType.WEB)); Set subscribeLists2 = new HashSet<>(Arrays.asList("daily_snacks", "brunch")); Set unsubscribeLists2 = new HashSet<>(Arrays.asList("promotions")); NamedUserScope namedUserScope1 = NamedUserScope.newBuilder() .setScopes(scopeTypes1) .setSubscribeLists(subscribeLists1) .setUnsubscribeLists(unsubscribeLists1) .build(); NamedUserScope namedUserScope2 = NamedUserScope.newBuilder() .setScopes(scopeTypes2) .setSubscribeLists(subscribeLists2) .setUnsubscribeLists(unsubscribeLists2) .build(); NamedUserScopedPayload namedUserScopedPayload = NamedUserScopedPayload.newBuilder() .addNamedUserScope(namedUserScope1) .addNamedUserScope(namedUserScope2) .build(); NamedUserScopedRequest request = NamedUserScopedRequest.newRequest("named_user_id", namedUserScopedPayload); Response response = client.execute(request); ``` --- ## Set or remove attributes on Named Users {#modifynameduserattributes} Set or remove attributes on a Named User. A single request body may contain a `set` or `remove` field, or both, or a single `set` field. If both `set` and `remove` fields are present and the intersection of the attributes in these fields is not empty, then a `400` will be returned. If an attribute request is partially valid, i.e., at least one attribute exists, Airship returns a `200` with a warning about the attributes that failed to update. The attributes listed in the `warnings` string will be in CSV format. [Jump to examples ↓](#modifynameduserattributes-examples) ### `POST /api/named_users/{named_user_id}/attributes` {{< note >}} Airship returns a `200` with a warning if you attempt to set attributes on a Named User that does not exist. {{< /note >}} {{< tip >}} If you wish to set attributes on multiple Named Users at once, we recommend using [/api/channels/attributes](/docs/developer/rest-api/ua/operations/channels/#modifychannelattributes) which supports an `audience` object in the request body. {{< /tip >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `named_user_id` | `string` | Required | The Named User you are setting the attributes for. | **Request body** **Content-Type:** `application/json` Type: `array` **Responses** **`200`** Success. If an attribute request is partially valid, i.e., at least one attribute exists, Airship returns a `200` with a warning string containing a CSV list of attributes that failed to update. Airship also returns a `200` with a warning if you attempt to set attributes on a `named_user`, even if the `named_user` does not exist. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` Set to `true` when status code is `200`. - **`warnings`** `string` Warnings encountered when updating Named User attributes. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/named_users/my_named_user/attributes HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "attributes": [ { "action": "set", "key": "firstName", "value": "Gyuri", "timestamp": "2020-09-19 12:00:00" }, { "action": "remove", "key": "birthDate", "timestamp": "2020-09-19 12:00:00" }, { "action": "set", "key": "lastName", "value": "Pataki", "timestamp": "2020-09-19 12:00:00" } ] } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, Attribute, ModifyAttributes ) client = BasicAuthClient( key='', secret='' ) set_major_league = Attribute( action="set", key="major_league", value="sf_giants") remove_minor_league = Attribute( action="remove", key="minor_league") set_position = Attribute( action="set", key="position", value="LF") modifications = ModifyAttributes( airship=client, attributes=[set_major_league, remove_minor_league, set_position], named_user="my_named_user" ) modifications.send() ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Attribute firstName = Attribute.newBuilder() .setAction(AttributeAction.SET) .setKey("firstName") .setValue("Gyuri") .setTimeStamp(DateTime.parse("2020-09-19T12:00:00Z")) .build(); Attribute birthDate = Attribute.newBuilder() .setAction(AttributeAction.REMOVE) .setKey("birthDate") .setTimeStamp(DateTime.parse("2020-09-19T12:00:00Z")) .build(); Attribute lastName = Attribute.newBuilder() .setAction(AttributeAction.SET) .setKey("lastName") .setValue("Pataki") .setTimeStamp(DateTime.parse("2020-09-19T12:00:00Z")) .build(); NamedUserAttributePayload payload = NamedUserAttributePayload.newBuilder() .addAttribute(firstName) .addAttribute(birthDate) .addAttribute(lastName) .build(); NamedUserAttributeRequest request = NamedUserAttributeRequest.newRequest("my_named_user", payload); Response response = client.execute(request); ``` --- # OAuth > Request an OAuth 2.0 token using Basic Auth or an assertion. ## Request token {#requestoauthtoken} Request an OAuth access token with Basic Auth or an assertion. When making a request with an assertion, do not provide the Basic Auth header. See also [OAuth 2.0](/docs/guides/getting-started/developers/api-security/#oauth-20) in the *Airship API Security* documentation. Use `oauth2.asnapius.com` for Airship's North American cloud site and `oauth2.asnapieu.com` for Airship's European cloud site when requesting an OAuth token. [Jump to examples ↓](#requestoauthtoken-examples) ### `POST /token` {{< note >}} When using the OAuth token for Airship API endpoints, make sure your requests are using the appropriate [domain in the base URL](/docs/developer/rest-api/ua/introduction/#servers). This example uses the OAuth token to list channels on Airship's North American cloud site: {{< highlight "bash" >}} curl --location 'https://api.asnapius.com/api/channels/' \ --header 'Accept: application/vnd.urbanairship+json; version=3;' \ --header 'Authorization: Bearer {OAUTH_ACCESS_TOKEN}' {{< /highlight >}} {{< /note >}} **Security:** - [basicOauth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicOauth) **Request headers:** | Name | Type | Required | Description | |------|------|----------|-------------| | `Content-Type` | `string` | Required | The request must have a `Content-Type` of `application/x-www-form-urlencoded`. | **Request body** **Content-Type:** `application/x-www-form-urlencoded` **One of:** - **`grant_type`** `string` **REQUIRED** Possible values: `client_credentials` - **`ipaddr`** `string` A list of CIDR representations of valid IP addresses to which the issued token is restricted. IP addresses can be sent as a URL-encoded, space-delimited list (example: `ipaddr=24.20.40.0%2F24%202001%3A4860%3A4860%3A%3A8888%2F32`) or as a list as expected in a query parameter form (example: `ipaddr=24.20.40.0/24&ipaddr=2001:4860:4860::8888/32`). - **`scope`** `string` <[OAuth Scope]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#oauthscope)> A list of scopes to which the issued token will be entitled. Scopes can be sent as URL-encoded, space-delimited list (example: `scope=chn%20nu`) or as a list as expected in a query parameter form (example: `scope=chn&scope=nu`). The value of the scope parameter is a list of space-delimited, case-sensitive strings. If multiple scopes are specified, their order does not matter. Each string adds an additional access range to the requested scope. For more information about scope values, see [OAuth token scopes](/docs/developer/rest-api/ua/api-auth-reference/#oauth-token-scopes) in the *Airship API Authorization Reference* documentation. * `att`: Attachments * `chn`: Channels * `tpl`: Content * `evt`: Events * `lst`: Lists * `nu`: Named Users * `pln`: Pipelines * `psh`: Push * `sch`: Schedules Possible values: `att`, `chn`, `tpl`, `evt`, `lst`, `nu`, `pln`, `psh`, `sch` - **`sub`** `object` <[Subject]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#subject)> **REQUIRED** A space-delimited set of identifiers for which subjects a token is allowed. An `app` subject is required. Example: `app:JQIMcndxIHWy2QISpt1SpZ`. A space-delimited set of identifiers for which subjects a token is allowed. Example: `app:JQIMcndxIHWy2QISpt1SpZ` * `app`: May operate on the given app - **`assertion`** `object` <[Assertion JWT]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#assertionjwt)> **REQUIRED** An encoded JWT that contains the required headers and claims and is signed with the client credentials' private key. A JSON Web Token (JWT) used for authorization in [OAuth token requests](/docs/developer/rest-api/ua/operations/oauth/#requestoauthtoken). The JWT must be signed with the private key corresponding to the `client_id` in the `kid` header using the ES384 algorithm. - **`grant_type`** `string` **REQUIRED** Possible values: `client_credentials` **Responses** **`200`** Returned on token request success. Response headers: | Name | Type | Description | |------|------|-------------| | `Cache-Control` | `string` | Possible values: `no-store` | | `Content-Type` | `string` | Possible values: `application/json` | | `Pragma` | `string` | Possible values: `no-cache` | Response body: **Content-Type:** `application/json` - **`access_token`** `string` The issued token that can be used for all endpoints as allowed by set scopes. - **`expires_in`** `integer` The number of seconds from the time the token is generated until it expires. - **`scope`** `string` <[OAuth Scope]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#oauthscope)> A space-delimited list of scopes of the issued token. There may be undocumented scopes in this list. The value of the scope parameter is a list of space-delimited, case-sensitive strings. If multiple scopes are specified, their order does not matter. Each string adds an additional access range to the requested scope. For more information about scope values, see [OAuth token scopes](/docs/developer/rest-api/ua/api-auth-reference/#oauth-token-scopes) in the *Airship API Authorization Reference* documentation. * `att`: Attachments * `chn`: Channels * `tpl`: Content * `evt`: Events * `lst`: Lists * `nu`: Named Users * `pln`: Pipelines * `psh`: Push * `sch`: Schedules Possible values: `att`, `chn`, `tpl`, `evt`, `lst`, `nu`, `pln`, `psh`, `sch` - **`token_type`** `string` The type of issued token. Possible values: `Bearer` **`400`** Token not generated. Response body: **Content-Type:** `application/json` - **`error`** `string` **REQUIRED** Error code. Possible values: `invalid_scope`, `invalid_request`, `invalid_grant`, `unauthorized_client`, `unsupported_grant_type`, `invalid_client` - **`error_description`** `string` A plain-text description of the error. **`401`** Unauthorized. Response headers: | Name | Type | Description | |------|------|-------------| | `WWW-Authenticate` | `string` | The HTTP authentication methods that can be used to request an access token. | Response body: **Content-Type:** `application/json` - **`error`** `string` **REQUIRED** Error code. Possible values: `invalid_client` - **`error_description`** `string` A plain-text description of the error. **`406`** Not acceptable. Response body: **Content-Type:** `application/json` - **`error`** `string` **REQUIRED** Error code. Possible values: `invalid_request` - **`error_description`** `string` A plain-text description of the error. **Examples** *Example request token with Basic Auth* ```http POST /token HTTP/1.1 Host: oauth2.asnapius.com Content-Type: application/x-www-form-urlencoded Accept: application/json Authorization: Basic grant_type=client_credentials&sub=app:JQIMcndxIHWy2QISpt1SpZ&scope=chn&scope=nu&ipaddr=24.20.40.0/24&ipaddr=2001:4860:4860::8888/32 ``` ```http HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Pragma: no-cache { "access_token": "", "token_type": "Bearer", "scope": "chn nu", "expires_in": 3600 } ``` ```java OAuthCredentials oAuthCredentials = OAuthCredentials.newBuilder("") .setClientSecret("") .setSub("") .setScopes(Arrays.asList("","","<...>")) .setIpAddresses(Arrays.asList("","",<...>)) .build(); UrbanAirshipClient oAuthClient = UrbanAirshipClient.newBuilder() .setKey("yourAppKey") .setOAuthCredentials(oAuthCredentials) .build(); ``` *Example request token with assertion* ```http POST /token HTTP/1.1 Host: oauth2.asnapius.com Content-Type: application/x-www-form-urlencoded Accept: application/json grant_type=client_credentials&assertion= ``` ```http HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Pragma: no-cache { "access_token": "", "token_type": "Bearer", "scope": "chn nu", "expires_in": 3600 } ``` ```java OAuthCredentials oAuthCredentials = OAuthCredentials.newBuilder("") .setAssertionJWT("") .build(); UrbanAirshipClient oAuthClient = UrbanAirshipClient.newBuilder() .setKey("") .setOAuthCredentials(oAuthCredentials) .build(); ``` ```python # The python OAuth client handles JWT creation # and token refresh automatically. # Once instantiated, this can be used as any other Airship client. airship_client = OAuthClient( client_id="", private_key="", key="", scope=["",], id_addr=["",], timeout="", retries="" ) ``` ```ruby require 'urbanairship' UA = Urbanairship app_key = '' oauth = UA::Oauth.new( client_id: '', key: app_key, assertion_private_key: '', scopes: ['psh', 'chn'], # Optional ip_addresses: ['23.74.131.15/22'], # Optional oauth_server: 'api.asnapieu.com' # Optional ) airship = UA::Client.new(key: app_key, oauth: oauth) ``` --- ## Verify public key {#getkeyverification} Retrieve the public key of a key ID. Use `oauth2.asnapius.com` for Airship's North American cloud site and `oauth2.asnapieu.com` for Airship's European cloud site when verifying an OAuth public key. [Jump to examples ↓](#getkeyverification-examples) ### `GET /verify/public_key/{kid}` **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `kid` | `string` | Required | The private key ID used to sign the token. Example: `8817e96` | **Responses** **`200`** Returned on success with the public key for the given `kid`. Response headers: | Name | Type | Description | |------|------|-------------| | `Cache-Control` | `string` | The response contains a `Cache-Control` header which must be respected. | Response body: **Content-Type:** `application/x-pem-file` Type: `string` **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/json` Type: `object` **Examples** *Example verify public key* ```http GET /verify/public_key/8817e96 HTTP/1.1 Host: oauth2.asnapius.com Accept: text/plain ``` ```http HTTP/1.1 200 OK Content-Type: application/x-pem-file Cache-Control: max-age=600, must-revalidate -----BEGIN PUBLIC KEY----- MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7tcTz03ypC7PSPa73Cbgl7AbDDo+92eH DWgjAi6vt1gmlHE35e+GhpcwbywBByOiooY+5bvfUHkc0aKy4R8VbBK0rYwlp8B+ fxyDr9Ye/oiUewMwwlp0z5AMPjgBUIKS -----END PUBLIC KEY----- ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PublicKeyVerificationRequest request = PublicKeyVerificationRequest.newRequest(""); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship app_key = '' oauth = UA::Oauth.new( client_id: '', key: app_key, assertion_private_key: '', scopes: ['psh', 'chn'], # Optional ip_addresses: ['23.74.131.15/22'], # Optional oauth_server: 'api.asnapieu.com' # Optional ) public_key = oauth.verify_public_key('') ``` --- # Open Channels > Open Channels are custom communication channels that you can configure for messaging, using the same segmentation and scheduling tools available on natively-supported platforms (iOS, Android, etc.). With Open Channels, you define a new open platform, e.g., SMS, Slack, Acme™ Smart Toasters, and register the new platform with Airship. If you are sending through the [Push API](/developer/rest-api/ua/operations/push/), platform overrides for open platforms are covered in [Open Channel Overrides](/developer/rest-api/ua/schemas/platform-overrides/#openchanneloverrideobject). For open channel lookup, use the [Channel Lookup endpoint](/developer/rest-api/ua/operations/channels/#getchannel). ## Open channel tags {#modifyopenchanneltags} Manipulate a single open channel’s tags. Open channels are identified by `address`, not by their `channel_id`. [Jump to examples ↓](#modifyopenchanneltags-examples) ### `POST /api/channels/open/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per channel. Adding more than 1,000 tags per channel can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per channel, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Adds the specified tags to the channel. Tags that are already present are not modified/removed as a result of this operation. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** The request body containing an address and `open_platform_name`. **OBJECT PROPERTIES** - **`address`** `string` **REQUIRED** Where notifications sent to this `channel_id` will be sent. Examples: email address, phone number. If missing, `channel_id` must be present. The `address` is one-to-one with the `channel_id`. New addresses on existing channels will overwrite old associations. Example: `new_email@example.com` - **`open_platform_name`** `string` **REQUIRED** An alphanumeric string that must be the name of a pre-created open platform object. Min length: 1, Max length: 128 Example: `twitter` - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Removes the specified tags from the channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Assigns a list of tags exactly. Any previously set tags that are not in this current list will be removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** Returns OK for success. If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 is returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/open/tags HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "address": "Number Four", "open_platform_name": "cylon" }, "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } } ``` ```http HTTP/1.1 200 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok":true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); OpenChannelTagRequest openChannelTagRequest = OpenChannelTagRequest.newRequest() .addOpenChannel("Number Four","cyclon") .addTags("CRM_Delux", Set.of("tag1","tag2")) .removeTags("CRM_Delux", Set.of("tag3","tag4")); Response response = client.execute(openChannelTagRequest); ``` ```python from urbanairship import ( BasicAuthClient, OpenChannel ) client = BasicAuthClient( key='', secret='' ) channel = OpenChannel(airship=client) channel.address = 'Number Four' channel.open_platform = 'cylon' channel.tags = ['tag1', 'tag2', 'tag3'] response = channel.update() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') open_channel = UA::OpenChannel.new(client: airship) open_channel.opt_in = true open_channel.address = 'Number Four' open_channel.open_platform = 'cylon' open_channel.channel_id = 'df6a6b50-9843-0304-d5a5-743f246a4946' open_channel.tags = ['tag1', 'tag2', 'tag3'] open_channel.update(set_tags: true) ``` --- ## Register new or update channel {#createorupdateopenchannel} Create a new open channel or update an existing open channel. [Jump to examples ↓](#createorupdateopenchannel-examples) ### `POST /api/channels/open` {{< note >}} A 200 status will be returned if an existing channel was found for the specified `open_platform_name` and address. Otherwise, a new channel will be created and a 200 status will be returned. {{< /note >}} {{< important >}} The master secret is required to update an open channel, otherwise a 401 Unauthorized response is returned. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** An open channel object. **Content-Type:** `application/json` - **`channel`** `object` **REQUIRED** Properties of the open channel object. **OBJECT PROPERTIES** - **`address`** `string` **REQUIRED** Where notifications sent to this `channel_id` will be sent. Examples: email address, phone number. If missing, `channel_id` must be present. The `address` is one-to-one with the `channel_id`. New addresses on existing channels will overwrite old associations. Example: `+1 5558675309` - **`locale_country`** `string` The two-letter country locale short code. Will set the `ua_locale_country` tag group to the specified value. Example: `US` - **`locale_language`** `string` The two-letter language locale short code. Will set the `ua_locale_language` tag group to the specified value. - **`open`** `object` **REQUIRED** Open channel-specific properties. **OBJECT PROPERTIES** - **`identifiers`** `object` Optional object with string-to-string key:value pairs that represent non-segmentable identifiers for the channel in your delivery systems. Delivered as part of webhook payloads. If present, the value will overwrite (not union with) existing identifier records. Max items: 100 Example: `[object Object]` - **`open_platform_name`** `string` **REQUIRED** The name of the open platform to which you are registering this channel. Example: `slack` - **`opt_in`** `boolean` **REQUIRED** If false, no payloads will be delivered for the channel. - **`tags`** `array[string]` A list of strings used for audience targeting. When used for this endpoint, operates like the `tags { set {}}` operation; specified tags are applied, and all other tags are removed. Min items: 1, Max items: 1000 Example: `one_tag,two_tag,red_tag,blue_tag` - **`timezone`** `string` An IANA tzdata identifier for the time zone as a string, e.g., `"America/Los_Angeles"`. Will set the `timezone` tag group tag with the specified value. Example: `America/Los_Angeles` - **`type`** `string` **REQUIRED** Required string. Possible values: `open` **Responses** **`200`** Returned if the new channel is created successfully or if an existing channel was found for the specified open_platform_name and address. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | Used for later API calls for this channel. | Response body: **Content-Type:** `application/json` - **`channel_id`** `string` Identifies the new open channel or the open channel you successfully updated. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`ok`** `boolean` Success. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`429`** Too many requests hit the API too quickly. For example, if we are not ready to create a channel for this payload; e.g., it is rate limited. You should wait before retrying the channel creation. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/open HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "channel": { "type": "open", "opt_in": true, "address": "Number Four", "tags": [ "toaster", "caprica" ], "timezone": "America/Los_Angeles", "locale_country": "US", "locale_language": "en", "open": { "open_platform_name": "cylon", "identifiers": { "model": "4" } } } } ``` ```http HTTP/1.1 200 OK Location: https://go.urbanairship.com/api/channels/df6a6b50-9843-0304-d5a5-743f246a4946 Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "channel_id": "df6a6b50-9843-0304-d5a5-743f246a4946" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); OpenChannel openChannel = OpenChannel.newBuilder() .setOpenPlatformName("cylon") .setOldAddress("Number Four") .addIdentifier("model", "4") .build(); Channel channel = Channel.newBuilder() .setOpenChannel(openChannel) .setChannelType(ChannelType.OPEN) .setOptIn(true) .setAddress("Number Four") .setTags(true) .addTag("toaster") .setTimeZone("America/Los_Angeles") .setLocaleCountry("US") .setLocaleLanguage("en") .build(); OpenChannelPayload payload = new OpenChannelPayload(channel); OpenChannelRequest request = OpenChannelRequest.newRequest(payload); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, OpenChannel ) client = BasicAuthClient( key='', secret='' ) channel = OpenChannel(airship=client) channel.address = 'Number Four' channel.open_platform = 'cylon' channel.opt_in = True channel.tags = ['toaster', 'caprica'] channel.identifiers = {'model': '4'} response = channel.create() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') open_channel = UA::OpenChannel.new(client: airship) open_channel.opt_in = true open_channel.address = 'Number Four' open_channel.open_platform = 'cylon' open_channel.create() ``` --- ## Uninstall open channels {#uninstallopenchannels} Uninstall a channel needing to know its Channel ID. You cannot send notifications to, or get channel information for, an uninstalled channel. [Jump to examples ↓](#uninstallopenchannels-examples) ### `POST /api/channels/open/uninstall` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** An `address` and the `open_platform_name` you want to uninstall the address from. **Content-Type:** `application/json` - **`address`** `string` **REQUIRED** Where notifications sent to this `channel_id` will be sent. Examples: email address, phone number. If missing, `channel_id` must be present. The `address` is one-to-one with the `channel_id`. New addresses on existing channels will overwrite old associations. Example: `new_email@example.com` - **`open_platform_name`** `string` **REQUIRED** An alphanumeric string that must be the name of a pre-created open platform object. Min length: 1, Max length: 128 Example: `twitter` **Responses** **`202`** The request has been accepted for processing. Response body: **Content-Type:** `application/json` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/open/uninstall HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "address": "Number Four", "open_platform_name": "cylon" } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); OpenChannelUninstallRequest openChannelUninstallRequest = OpenChannelUninstallRequest.newRequest("Number Four","cyclon"); Response response = client.execute(openChannelUninstallRequest); ``` ```python from urbanairship import ( BasicAuthClient, OpenChannel ) client = BasicAuthClient( key='', secret='' ) channel = OpenChannel(airship=client) channel.address = 'Number Four' channel.open_platform = 'cylon' response = channel.uninstall() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') cu = UA::OpenChannelUninstall.new(client: airship) cu.uninstall(address: 'Number Four', open_platform: 'cylon') ``` --- # Personalization > Use the `/templates` API to create templates and push templatized notifications. {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} ## Create template {#createtemplate} Create a new template. [Jump to examples ↓](#createtemplate-examples) ### `POST /api/templates` {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Request body** A single template object. **Content-Type:** `application/json` [Template object]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#templateobject) **Responses** **`201`** The template was created. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The URI for the template, used for later updates or sends. | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If `true`, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`template_id`** `string` A unique string identifying the template, used to call the template for pushing and other operations. Format: `uuid` Example: `0f7704e9-5dc0-4f7d-9964-e89055701b0a` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/templates HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name": "Welcome Message", "description": "Our welcome message", "variables": [ { "key": "TITLE", "name": "Title", "description": "e.g., Mr, Ms, Dr, etc.", "default_value": "" }, { "key": "FIRST_NAME", "name": "First Name", "description": "Given name", "default_value": null }, { "key": "LAST_NAME", "name": "Last Name", "description": "Family name", "default_value": null } ], "push": { "notification": { "alert": "Hello {{FIRST_NAME}}, this is your welcome message!" } } } ``` ```http HTTP/1.1 201 Created Location: https://go.urbanairship.com/api/templates/ef34a8d9-0ad7-491c-86b0-aea74da15161 Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "operation_id" : "9ce808c8-7176-45dc-b79e-44aa74249a5a", "template_id": "ef34a8d9-0ad7-491c-86b0-aea74da15161" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TemplateVariable titleVariable = TemplateVariable.newBuilder() .setKey("TITLE") .setName("Title") .setDescription("e.g., Mr, Ms, Dr, etc.") .setDefaultValue("") .build(); TemplateVariable firstNameVariable = TemplateVariable.newBuilder() .setKey("FIRST_NAME") .setName("First Name") .setDescription("Given name") .setDefaultValue(null) .build(); TemplateVariable lastNameVariable = TemplateVariable.newBuilder() .setKey("LAST_NAME") .setName("Last Name") .setDescription("Family name") .setDefaultValue("") .build(); PartialPushPayload partialPushPayload = PartialPushPayload.newBuilder() .setNotification(Notification.newBuilder() .setAlert("Hello {{TITLE}} {{FIRST_NAME}} {{LAST_NAME}}, this is your welcome message!") .build() ) .build(); TemplateRequest request = TemplateRequest.newRequest() .setName("Welcome Message") .setDescription("Our welcome message") .addVariable(titleVariable) .addVariable(firstNameVariable) .addVariable(lastNameVariable) .setPush(partialPushPayload); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Template, TemplateList, merge_data ) client = BasicAuthClient( key='', secret='' ) # Create a new template template = Template(client) template.name = 'Welcome Message' template.description = 'Our welcome message' template.variables = [ { 'key': 'TITLE', 'name': 'Title', 'description': 'e.g., Mr., Ms., Dr., etc.', 'default_value': '' }, { 'key': 'FIRST_NAME', 'name': 'First Name', 'description': 'Given name', 'default_value': None }, { 'key': 'LAST_NAME', 'name': 'Last Name', 'description': 'Family name', 'default_value': None } ] template.push = { 'notification': { 'alert': 'Hello {{TITLE}} {{FIRST_NAME}} {{LAST_NAME}}, this is your welcome message!' } } response = template.create() print(f"Template ID: {template.template_id}") # To get the template ID for future use # List all templates for template in TemplateList(client): print( f"Template ID: {template.template_id}\n" f"Created: {template.created_at}\n" f"Modified: {template.modified_at}\n" f"Last Used: {template.last_used}\n" f"Name: {template.name}\n" f"Description: {template.description}\n" f"Variables: {template.variables}\n" f"Push: {template.push}" ) # Send a push using a template push = client.create_push() push.device_types = ['ios'] push.audience = { 'ios_channel': 'b8f9b663-0a3b-cf45-587a-be880946e881' } push.merge_data = merge_data( template_id='ef34a8d9-0ad7-491c-86b0-aea74da15161', substitutions={ 'FIRST_NAME': 'Bob', 'LAST_NAME': 'Smith', 'TITLE': '' } ) response = push.send() ``` --- ## Delete template {#deletetemplate} Delete a template. If the template is successfully deleted, the response does not include a body. [Jump to examples ↓](#deletetemplate-examples) ### `DELETE /api/templates/{template_id}` {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `template_id` | `string` | Required | A required string ID of the template. | **Responses** **`200`** The template with given ID has been successfully deleted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If true, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http DELETE /api/templates/ef34a8d9-0ad7-491c-86b0-aea74da15161 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "a6394ff8-8a65-4494-ad06-677eb8b7ad6a" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TemplateDeleteRequest request = TemplateDeleteRequest.newRequest("ef34a8d9-0ad7-491c-86b0-aea74da15161"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Template, TemplateList, merge_data ) client = BasicAuthClient( key='', secret='' ) template_id = 'ef34a8d9-0ad7-491c-86b0-aea74da15161' # Delete via template lookup response = Template(client).lookup(template_id).delete() # OR, if you want to delete a template without fetching it from the API response = Template(client).delete(template_id) ``` --- ## List templates {#gettemplates} List all existing templates. Returns an array of template objects in the `templates` attribute. [Jump to examples ↓](#gettemplates-examples) ### `GET /api/templates` {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `page` | `integer` | | Specifies the desired page number. Defaults to 1. | | `page_size` | `integer` | | Specifies how many results to return per page. Has a default value of 25 and a maximum value of 100. | | `sort` | `string` | | Specifies the name of the field you want to sort results by. Defaults to `created_at`. Possible values: `created_at`, `modified_at`, `last_used` | | `order` | `string` | | Specifies the sort order as ascending (`asc`) or descending (`desc`). Defaults to `asc`. Possible values: `asc`, `desc` | **Responses** **`200`** Returned on success, with the JSON representation of the templates in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`count`** `integer` The number of templates in the current response; this is effectively the page size. - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` Example: `https://go.urbanairship.com/api/templates?page=2&page_size=1` - **`ok`** `boolean` **REQUIRED** Success. - **`prev_page`** `string` Link to the previous page, if available. Format: `url` - **`templates`** `array` <[Template object]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#templateobject)> An array of template objects. - **`total_count`** `integer` The total number of templates. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/templates HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: templates Count: 1 Total-Count: 1 Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "count": 1, "total_count": 1, "templates": [ { "id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "created_at": "2020-08-17T11:10:01Z", "modified_at": "2020-08-17T11:10:01Z", "last_used": null, "name": "Welcome Message", "description": "Our welcome message", "variables": [ { "key": "TITLE", "name": "Title", "description": "e.g., Mr, Ms, Dr, etc.", "default_value": "" }, { "key": "FIRST_NAME", "name": "First Name", "description": "Given name", "default_value": null }, { "key": "LAST_NAME", "name": "Last Name", "description": "Family name", "default_value": null } ], "push": { "notification": { "alert": "Hello {{FIRST_NAME}}, this is your welcome message!" } } } ], "next_page": null, "prev_page": null } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TemplateListingRequest request = TemplateListingRequest.newRequest(); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Template, TemplateList, merge_data ) client = BasicAuthClient( key='', secret='' ) # List all templates for template in TemplateList(client): print( f"Template ID: {template.template_id}\n" f"Created: {template.created_at}\n" f"Modified: {template.modified_at}\n" f"Last Used: {template.last_used}\n" f"Name: {template.name}\n" f"Description: {template.description}\n" f"Variables: {template.variables}\n" f"Push: {template.push}" ) ``` --- ## Look up a template {#gettemplate} Fetch the current definition of a single template. [Jump to examples ↓](#gettemplate-examples) ### `GET /api/templates/{template_id}` {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `template_id` | `string` | Required | A required string ID of the template. | **Responses** **`200`** Returned on success, with the JSON representation of the template in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If true, the operation completed successfully and returns an expected response. - **`template`** `object` <[Template object]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#templateobject)> A template object is a skeleton for a push. This is the object used for template creation, and returned by the template listing and lookup endpoints. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/templates/ef34a8d9-0ad7-491c-86b0-aea74da15161 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: template Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "template": { "id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "created_at": "2020-08-17T11:10:02Z", "modified_at": "2020-08-17T11:10:02Z", "last_used": null, "name": "Welcome Message", "description": "Our welcome message", "variables": [ { "key": "TITLE", "name": "Title", "description": "e.g., Mr, Ms, Dr, etc.", "default_value": "" }, { "key": "FIRST_NAME", "name": "First Name", "description": "Given name", "default_value": null }, { "key": "LAST_NAME", "name": "Last Name", "description": "Family name", "default_value": null } ], "push": { "notification": { "alert": "Hello {{FIRST_NAME}}, this is your welcome message!" } } } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TemplateListingRequest request = TemplateListingRequest.newRequest("ef34a8d9-0ad7-491c-86b0-aea74da15161"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Template, TemplateList, merge_data ) client = BasicAuthClient( key='', secret='' ) template_id = 'ef34a8d9-0ad7-491c-86b0-aea74da15161' template = Template(client).lookup(template_id) print( template.template_id, template.created_at, template.modified_at, template.last_used, template.name, template.description, template.variables, template.push ) ``` --- ## Push to template {#pushtotemplate} Send a push notification based on a template to a list of devices. The body of the request must be a single push template payload or an array of one or more push template payloads. [Jump to examples ↓](#pushtotemplate-examples) ### `POST /api/templates/push` {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** A single push template payload or an array of push template payloads. Provide an override with any variable that has a `null` default value. For example, if you created a template with the variable `FIRST_NAME`, and that variable has `null` as a default value, you must provide a substitution for `FIRST_NAME` when pushing to that template. **Content-Type:** `application/json` **One of:** - [Push template payload]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#pushtemplatepayload) A push template payload defines a push by overriding the variables defined in a specific template object. Specifically, a push template object specifies push audience and device types, along with substitutions for the variables defined in a template. - `array` **Responses** **`202`** The push notification has been accepted for processing. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If true, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`push_ids`** `array[string]` An array of the push IDs for this operation. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/templates/push HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "device_types": [ "ios" ], "audience": { "ios_channel": "b8f9b663-0a3b-cf45-587a-be880946e881" }, "merge_data": { "template_id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "substitutions": { "FIRST_NAME": "Bob", "LAST_NAME": "Smith", "TITLE": "" } } } ``` ```http HTTP/1.1 202 Accepted Content-Length: 123 Data-Attribute: push_ids Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "operation_id" : "df6a6b50-9843-0304-d5a5-743f246a4946", "push_ids": [ "1cbfbfa2-08d1-92c2-7119-f8f7f670f5f6" ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TemplatePushPayload payload = TemplatePushPayload.newBuilder() .setAudience(Selectors.iosChannel("b8f9b663-0a3b-cf45-587a-be880946e881")) .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS)) .setMergeData(TemplateSelector.newBuilder() .setTemplateId("ef34a8d9-0ad7-491c-86b0-aea74da15161") .addSubstitution("FIRST_NAME", "Bob") .addSubstitution("LAST_NAME", "Smith") .addSubstitution("TITLE", "Mr.") .build()) .build(); TemplatePushRequest request = TemplatePushRequest.newRequest() .addTemplatePushPayload(payload); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Template, TemplateList, merge_data ) client = BasicAuthClient( key='', secret='' ) # Send a push using a template push = client.create_push() push.device_types = ['ios'] push.audience = { 'ios_channel': 'b8f9b663-0a3b-cf45-587a-be880946e881' } push.merge_data = merge_data( template_id='ef34a8d9-0ad7-491c-86b0-aea74da15161', substitutions={ 'FIRST_NAME': 'Bob', 'LAST_NAME': 'Smith', 'TITLE': '' } ) response = push.send() ``` --- ## Schedule a templated push {#scheduletemplatedpush} Schedule a push notification based on a template to a list of devices. Like a standard template-based push, the body of the request includes one or more push template payloads along with a schedule object determining when the template-based push should be sent. [Jump to examples ↓](#scheduletemplatedpush-examples) ### `POST /api/templates/schedules` {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** An array of scheduled pushes. **Content-Type:** `application/json` Type: `array` **Responses** **`202`** The scheduled push has been accepted for processing. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** Success. - **`operation_id`** `string` A unique string which identifies a single API call, and can be used to group multiple entities or side effects as related, in reporting and troubleshooting logs. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`schedule_ids`** `array[string]` An array of schedule IDs. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`schedule_urls`** `array[string]` An array of schedule URLs. The URL for each schedule is the schedules endpoint, appended with the `schedule_id` of the schedule. Min items: 0, Max items: 100 Example: `https://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed109` - **`schedules`** `array` <[Schedule object]({{< ref "/developer/rest-api/ua/schemas/schedules/" >}}#scheduleobject)> An array of schedule objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/templates/schedules HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json [ { "name": "Hello Bob", "schedule": { "scheduled_time": "2020-05-02T22:00:00Z" }, "device_types": [ "ios" ], "audience": { "ios_channel": "b8f9b663-0a3b-cf45-587a-be880946e881" }, "merge_data": { "template_id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "substitutions": { "FIRST_NAME": "Bob", "LAST_NAME": "Takahashi", "TITLE": null } } }, { "name": "Hello Joe", "schedule": { "scheduled_time": "2020-05-05T18:00:00Z" }, "device_types": [ "android" ], "audience": { "android_channel": "df6a6b50-9843-0304-d5a5-743f246a4946" }, "merge_data": { "template_id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "substitutions": { "FIRST_NAME": "Joe", "LAST_NAME": "Smith", "TITLE": "Sir" } } } ] ``` ```http HTTP/1.1 202 Accepted Content-Length: 123 Data-Attribute: schedule_urls Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "operation_id" : "efb18e92-9a60-6689-45c2-82fedab36399", "schedule_urls" : [ "http://go.urbanairship/api/schedules/a0cef4f9-1fcd-47ef-b459-01f432b64043", "http://go.urbanairship/api/schedules/fe2dab5e-f837-4707-8d0c-0e8c589ef4cf" ], "schedule_ids" : [ "a0cef4f9-1fcd-47ef-b459-01f432b64043", "fe2dab5e-f837-4707-8d0c-0e8c589ef4cf" ], "schedules" : [ { "url" : "http://go.urbanairship/api/schedules/a0cef4f9-1fcd-47ef-b459-01f432b64043", "name": "Hello Joe", "schedule" : { "..." }, "push" : { "..." }, "push_ids": [ "6a5ecb9c-46ee-4af4-9ced-9308121afaf9" ] }, { "url" : "http://go.urbanairship/api/schedules/fe2dab5e-f837-4707-8d0c-0e8c589ef4cf", "name": "Hello Bob", "schedule" : { "..." }, "push" : { "..." }, "push_ids": [ "5162bbf8-7de7-4040-a64d-e018b71f02f6" ] } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TemplateScheduledPushPayload payload = TemplateScheduledPushPayload.newBuilder() .setAudience(Selectors.iosChannel("b8f9b663-0a3b-cf45-587a-be880946e881")) .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS)) .setMergeData(TemplateSelector.newBuilder() .setTemplateId("ef34a8d9-0ad7-491c-86b0-aea74da15161") .addSubstitution("FIRST_NAME", "Bob") .addSubstitution("LAST_NAME", "Takahashi") .addSubstitution("TITLE", "Dr.") .build()) .setSchedule(Schedule.newBuilder() .setScheduledTimestamp(DateTime.parse("2020-05-05T18:00:00Z")) .build()) .build(); TemplateScheduledPushRequest request = TemplateScheduledPushRequest.newRequest() .addTemplateScheduledPushPayload(payload); Response response = client.execute(request); ``` --- ## Update template {#updatetemplate} Update a template. The request body is a partially-defined template object, containing the field(s) you want to change and their updated values. [Jump to examples ↓](#updatetemplate-examples) ### `POST /api/templates/{template_id}` {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `template_id` | `string` | Required | A required string ID of the template. | **Request body** **Content-Type:** `application/json` - **`description`** `string` The description of the template. - **`name`** `string` **REQUIRED** The name of the template. - **`push`** `object` <[Template push object]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#templatepushobject)> A partial push object describing everything about a push notification, except for the `audience` and `device_types` keys (which are defined in the [Push template payload](/docs/developer/rest-api/ua/schemas/personalization-template-objects/#pushtemplatepayload)) and the `message` key (which is incompatible with templates). - **`variables`** `array` <[Template variables]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#templatevariableobject)> An array of variable specifications. **Responses** **`200`** Returned if the template has been successfully updated. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` **REQUIRED** If true, the operation completed successfully and returns an expected response. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/templates/ef34a8d9-0ad7-491c-86b0-aea74da15161 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name": "Welcome Message", "description": "Our welcome message", "push": { "notification": { "alert": "Hello {{FIRST_NAME}} {{LAST_NAME}}, this is your welcome message!" } } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "df6a6b50-9843-0304-d5a5-743f246a4946" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PartialPushPayload partialPushPayload = PartialPushPayload.newBuilder() .setNotification(Notification.newBuilder() .setAlert("Hello {{FIRST_NAME}} {{LAST_NAME}}, this is your welcome message!") .build() ) .build(); TemplateRequest request = TemplateRequest.newRequest("ef34a8d9-0ad7-491c-86b0-aea74da15161") .setName("Welcome Message") .setDescription("Our welcome message") .setPush(partialPushPayload); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Template, TemplateList, merge_data ) client = BasicAuthClient( key='', secret='' ) template_id = 'ef34a8d9-0ad7-491c-86b0-aea74da15161' updated_template = Template(client) updated_template.push = { 'notification': { 'alert': 'Hi {{FIRST_NAME}} {{LAST_NAME}}!' } } response = updated_template.update(template_id) ``` *Alternatively, call the lookup function on your updated template:* ```python from urbanairship import ( BasicAuthClient, Template, TemplateList, merge_data ) client = BasicAuthClient( key='', secret='' ) template_id = 'ef34a8d9-0ad7-491c-86b0-aea74da15161' updated_template = Template(client).lookup(template_id) updated_template.push = { 'notification': { 'alert': 'Greetings {{TITLE}} {{FIRST_NAME}} {{LAST_NAME}}!' } } response = updated_template.update() ``` --- ## Validate a template {#validatetemplate} This endpoint accepts the same range of payloads as `/api/template/push`, but only parses and validates the payload. It does not actually send a push. [Jump to examples ↓](#validatetemplate-examples) ### `POST /api/templates/push/validate` {{< note >}} The Personalization (`/templates`) API is deprecated. Instead, [create templates in the Airship dashboard](/docs/guides/personalization/content/templates/) or use the [Content API](/docs/developer/rest-api/ua/operations/content/), and send using the [Bulk sending](/docs/developer/rest-api/ua/operations/bulk-sending/) or [Automation](/docs/developer/rest-api/ua/operations/automation/) APIs. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** A single push template payload or an array of push template payloads. **Content-Type:** `application/json` **One of:** - [Push template payload]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#pushtemplatepayload) A push template payload defines a push by overriding the variables defined in a specific template object. Specifically, a push template object specifies push audience and device types, along with substitutions for the variables defined in a template. - `array` **Responses** **`200`** The payload was valid. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/templates/push/validate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "device_types": [ "ios" ], "audience": { "ios_channel": "b8f9b663-0a3b-cf45-587a-be880946e881" }, "merge_data": { "template_id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "substitutions": { "FIRST_NAME": "Bob", "LAST_NAME": "Smith", "TITLE": "" } } } ``` ```http HTTP/1.1 200 OK Content-Length: 123 Data-Attribute: push_ids Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TemplatePushPayload payload = TemplatePushPayload.newBuilder() .setAudience(Selectors.iosChannel("b8f9b663-0a3b-cf45-587a-be880946e881")) .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS)) .setMergeData(TemplateSelector.newBuilder() .setTemplateId("ef34a8d9-0ad7-491c-86b0-aea74da15161") .addSubstitution("FIRST_NAME", "Bob") .addSubstitution("LAST_NAME", "Smith") .addSubstitution("TITLE", "Mr.") .build()) .build(); TemplatePushRequest request = TemplatePushRequest.newRequest() .addTemplatePushPayload(payload) .setValidateOnly(true); Response response = client.execute(request); ``` --- # Push > Send notifications or rich messages to supported channels, or validate JSON payloads. ## Delete message from inbox {#deletemessage} Delete a Message Center message completely, removing it from every user’s inbox. This is an asynchronous call; a success response means that the deletion has been queued for processing. This delete call will work with either the `message_id` or the `push_id` of the accompanying push notification. This endpoint will not work with a `group_id` from an automated message or a push to local time delivery. To delete a rich message that was part of an automated or local time delivery, you must use the relevant `push_id` from the operation. [Jump to examples ↓](#deletemessage-examples) ### `DELETE /api/user/messages/{push_id}` {{< note >}} For time-sensitive messages, consider including an `expiry` time as detailed in the [In-App Message Object](/docs/developer/rest-api/ua/schemas/others/#inappobject). Setting an `expiry` value eliminates the need to manually remove messages. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `push_id` | `string` | Required | The `push_id` or `message_id` of the Rich Message you want to delete from users` inboxes. | **Responses** **`202`** The request has been accepted for processing. Response body: **Content-Type:** `application/json` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http DELETE /api/user/messages/(push_id) HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import BasicAuthClient, Push client = BasicAuthClient( key='', secret='' ) Push.message_center_delete(airship=client, push_id="941086fd-f7db-493b-a8a7-1f5a7dc6aae4") ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); InboxDeleteRequest request = InboxDeleteRequest.newRequest("68b2d71f-1c10-4592-bd96-2725aee0ae57"); Response response = client.execute(request); ``` --- ## Delete multiple messages from inbox {#batchdeletemessages} Deletes multiple Message Center messages (up to 50 messages per request) completely, removing them from every user’s inbox. This is an asynchronous call; a success response means that the deletion has been queued for processing. It is not possible to delete Message Center messages generated by an automation, a recurring message, or a Sequence. [Jump to examples ↓](#batchdeletemessages-examples) ### `POST /api/user/messages/batch-delete` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Request body** A request body containing an array of message IDs to be deleted. **Content-Type:** `application/json` - **`message_ids`** `array[string]` **REQUIRED** Array of Message IDs. Min items: 1, Max items: 50 **Responses** **`202`** The request has been accepted for processing. Response body: **Content-Type:** `application/json` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/user/messages/batch-delete HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "message_ids": [ "drKa4OdxEeyhSwJC9TkdtQ", "W5ersOdxEeyvwAJCxz92iA" ] } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "deleted_message_ids": [ "W5ersOdxEeyvwAJCxz92iA", "drKa4OdxEeyhSwJC9TkdtQ" ], "errors": [] } ``` ```http HTTP/1.1 404 Not Found Content-Type: application/vnd.urbanairship+json; version=3 { "deleted_message_ids": [], "errors": [ { "message_id": "drKa4OdxEeyhSwJC9Tkdt1", "error_message": "Message not found.", "error_code": 40404 }, { "message_id": "W5ersOdxEeyvwAJCxz92i1", "error_message": "Message not found.", "error_code": 40404 } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); List arrayList = new ArrayList<>(); arrayList.add("9dWD3LBIS5iZ51Y1GwOi4Q"); arrayList.add("lsDtpTBJTN6KpQTwfOSNbw"); InboxBatchDeleteRequest inboxBatchDeleteRequest = InboxBatchDeleteRequest.newRequest(arrayList); Response response = client.execute(inboxBatchDeleteRequest); ``` --- ## Send a push {#sendpush} Send a push notification to a specified audience. The body of the request must be a [Push object](/docs/developer/rest-api/ua/schemas/others/#pushobject) or an array of push objects. [Jump to examples ↓](#sendpush-examples) ### `POST /api/push` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** A single push object or an array of push objects. **Content-Type:** `application/json` **One of:** - [Push object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#pushobject) A push object describes everything about a push notification, including the audience and push payload. A push object is composed of up to seven attributes. - `array` **Responses** **`202`** The push notification has been accepted for processing. The response contains `push_id`, `message_id`, and/or `content_url` arrays based on the type of push. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`content_urls`** `array[string]` An array of URLs where the push payload contains a landing page action. Min items: 0, Max items: 100 - **`localized_ids`** `array[string]` An array of identifiers used for reporting. Each ID represents a localized message (push object with `localizations` array). - **`message_ids`** `array[string]` An array of message IDs, each uniquely identifying a Message Center message. - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string identifying the operation, useful for reporting and troubleshooting. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`push_ids`** `array[string]` An array of push IDs, each uniquely identifying a push. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`429`** Too many requests hit the API too quickly. For example, if we are not ready to create a channel for this payload; e.g., it is rate limited. You should wait before retrying the channel creation. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/push HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "ios_channel": "9c36e8c7-5a73-47c0-9716-99fd3d4197d5" }, "notification": { "alert": "Hello!" }, "device_types": [ "ios" ] } ``` ```http HTTP/1.1 202 Accepted Data-Attribute: push_ids Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "df6a6b50-9843-0304-d5a5-743f246a4946", "push_ids": [ "9d78a53b-b16a-c58f-b78d-181d5e242078" ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PushPayload payload = PushPayload.newBuilder() .setAudience(Selectors.iosChannel("9c36e8c7-5a73-47c0-9716-99fd3d4197d5")) .setNotification(Notifications.alert("Hello!")) .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS)) .build(); PushRequest request = PushRequest.newRequest(payload); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Push ) client = BasicAuthClient( key="", secret="" ) push = Push(client) push.audience = {'ios_channel': '9c36e8c7-5a73-47c0-9716-99fd3d4197d5'} push.notification = {'alert': 'Hello!'} push.device_types = ['ios'] push.send() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') push = airship.create_push push.audience = UA.or( UA.ios_channel('9c36e8c7-5a73-47c0-9716-99fd3d4197d5')) push.notification = UA.notification(alert: 'Hello!') push.device_types = UA.device_types(['ios']) push.send_push ``` *Example push with localizations* ```http POST /api/push HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "device_types": [ "ios", "android" ], "audience": { "tag": "needs_a_greeting", "group": "new_customer" }, "notification": { "alert": "Hi!" }, "localizations": [ { "language": "de", "country": "AT", "notification": { "alert": "Grüss Gott" } }, { "language": "de", "country": "DE", "notification": { "alert": "Guten Tag" } } ] } ``` ```http HTTP/1.1 202 Accepted Data-Attribute: push_ids Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "df6a6b50-9843-0304-d5a5-743f246a4946", "push_ids": [ "9d78a53b-b16a-c58f-b78d-181d5e242078", "1cbfbfa2-08d1-92c2-7119-f8f7f670f5f6", "939c3796-a755-413b-a36b-3026b1f92df8" ], "localized_ids": [ "1a38a2ba-c174-d32f-d01b-481a5d241934" ] } ``` ```python from urbanairship import ( BasicAuthClient, Push ) client = BasicAuthClient( key="", secret="" ) push = Push(client) push.audience = { 'tag': 'needs_a_greeting', 'group': 'new_customer' } push.notification = {'alert': 'Hi!'} push.localizations = [ { 'country': 'at', 'language': 'de', 'notification': {'alert': "Grüss Gott"} }, { 'country': 'de', 'language': 'de', 'notification': {'alert': "Guten Tag"} } ] push.device_types = ['ios', 'android'] push.send() ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Localization localization = Localization.newBuilder() .setCountry("AT") .setLanguage("de") .setNotification(Notifications.alert("Grüss Gott")) .build(); PushPayload payload = PushPayload.newBuilder() .setAudience(Selectors.or(Selectors.tagWithGroup("needs_a_greeting", "new_customer"))) .addLocalization(localization) .setNotification(Notifications.alert("Hi!")) .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID)) .build(); PushRequest request = PushRequest.newRequest(payload); Response response = client.execute(request); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') push = airship.create_push push.audience = UA.tag("needs_a_greeting", group:'new_customer') push.notification = UA.notification(alert: 'Hi!') push.device_types = UA.device_types(['ios']) push.localizations = { "language": "de", "country": "AT", "notification": { "alert": "Grüss Gott" } } push.send_push ``` *Example email being sent using Push API with template ID* ```http POST /api/push HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "tag": "needs_a_greeting", "group": "new_customer" }, "device_types": [ "email" ], "notification": { "email": { "message_type": "commercial", "reply_to": "no-reply@airship.com", "sender_address": "team@airship.com", "sender_name": "Airship", "template": { "template_id": "876624ff-0120-4364-bf02-dba3d0cb5b85" } } } } ``` ```http HTTP/1.1 202 Accepted Data-Attribute: push_ids Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "be97b696-8d6b-4aec-ac50-c9cfc4be57d6", "push_ids": [ "72ce9ade-aa71-4fbe-b960-246f1a2ca9ee" ], "message_ids": [], "content_urls": [], "localized_ids": [] } ``` --- ## Validate a push {#validatepush} Accept the same range of payloads as POSTing to `/api/push`, but parse and validate only, without sending any pushes. The body of the request must be a [Push Object](/docs/developer/rest-api/ua/schemas/others/#pushobject) or an array of push objects. [Jump to examples ↓](#validatepush-examples) ### `POST /api/push/validate` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** A single push object or an array of push objects. **Content-Type:** `application/json` **One of:** - [Push object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#pushobject) A push object describes everything about a push notification, including the audience and push payload. A push object is composed of up to seven attributes. - `array` **Responses** **`200`** The payload was valid. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/push/validate HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "ios_channel": "9c36e8c7-5a73-47c0-9716-99fd3d4197d5" }, "notification": { "alert": "Hello!" }, "device_types": [ "ios" ] } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```python from urbanairship import ( BasicAuthClient, Push ) from urbanairship.push.payload import notification, ios, android, web client = BasicAuthClient( key="", secret="" ) push = Push(client) push.audience = {'ios_channel': '9c36e8c7-5a73-47c0-9716-99fd3d4197d5'} push.notification = notification(alert='Hello!') push.device_types = ['ios'] push.validate() ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PushPayload payload = PushPayload.newBuilder() .setAudience(Selectors.iosChannel("9c36e8c7-5a73-47c0-9716-99fd3d4197d5")) .setNotification(Notifications.alert("Hello!")) .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS)) .build(); PushRequest request = PushRequest.newRequest(payload).setValidateOnly(true); Response response = client.execute(request); ``` --- # Regions > The Region API endpoints provide a listing and detail for all of your defined entry/exit regions, including custom shapes (polygons) and circles (point/radius). ## Region listing {#getregions} Get a paginated list regions. The result is an array of [Region objects](/docs/developer/rest-api/ua/schemas/regions/#regionobject) under the `"regions"` key. [Jump to examples ↓](#getregions-examples) ### `GET /api/regions` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `limit` | `integer` | | Determines the number of results per page. Defaults to 100, with a maximum of 1,000 regions per page. Setting a `limit` greater than 1,000 returns a 400 response. Max: 1000 | | `start` | `integer` | | A zero-based integer offset into the ordered list of regions, useful for addressing pages directly. | **Responses** **`200`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`count`** `integer` The total number of regions returned. - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` Example: `https://go.urbanairship.com/api/regions?limit=100&start=100` - **`ok`** `boolean` Success. - **`regions`** `array` <[Region object]({{< ref "/developer/rest-api/ua/schemas/regions/" >}}#regionobject)> An array of region objects. **`400`** Returned when `limit` is greater than 1,000. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/regions/?limit=100&start=100 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: regions Link: ; rel=next Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "next_page": "https://go.urbanairship.com/api/regions?limit=100&start=100", "count": 100, "regions": [ { "region_id": "abe5deb3-01d0-436e-8c5d-94b6421a01e0", "name": "My Favorite Place", "created_at": "2020-06-09T12:34:56", "updated_at": "2020-06-09T12:34:56", "geofence": { "type": "POLYGON", "points": [ { "latitude": 90.0, "longitude": 120.0 }, { "latitude": 45.0, "longitude": 120.0 }, { "latitude": 0.0, "longitude": 0.0 } ] }, "beacons": [ { "name": "entryway", "id": "VLSHZAOEXOFCMLDVTKFQ" }, { "name": "Exhibit A", "id": "ZAQYMNOZKRFCRPYEUCZI" } ], "attributes": { "store_name": "Tonali's Donuts" }, "source_info": { "source": "GIMBAL", "region_id": "C56654BC0C3243D6A4B7A3673560D6F8", "vendor_href": "https://manager.gimbal.com/api/v2/places/C56654BC0C3243D6A4B7A3673560D6F8" } } ] } ``` --- ## Region lookup {#getregion} Get details for a specific region. [Jump to examples ↓](#getregion-examples) ### `GET /api/regions/{region_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `region_id` | `string` | Required | The region you want to lookup. | **Responses** **`200`** Returns OK for success. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If true, indicates success. Example: `true` - **`region`** `object` <[Region object]({{< ref "/developer/rest-api/ua/schemas/regions/" >}}#regionobject)> A Region object describes a geographical boundary or set of hardware identifiers and associated attributes that correspond to a physical location of relevance to the application or application owner. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/regions/7d4d9a5c-eff5-40f2-b648-4352c166e878 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: region Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "region": { "region_id": "7dbd9a5c-eff5-40f2-b648-4352c1668878", "created_at": "2020-08-24T23:15:22.900", "updated_at": "2020-08-24T23:15:22.900", "name": "Alberta Park", "source_info": { "source": "GIMBAL", "region_id": "C56654BC0C3243D6A4B7A3673560D6F8", "vendor_href": "https://manager.gimbal.com/api/v2/places/C56654BC0C3243D6A4B7A3673560D6F8" }, "geofence": { "type": "CIRCLE", "center": { "latitude": 45.56447530000002, "longitude": -122.64461097354126 }, "radius": 200 }, "attributes": { "park_name": "alberta", "type": "park" } } } ``` --- # Reports > Report API endpoints let you retrieve information about push notifications that you have sent. ## Activity log report {#getactivitylogreport} Returns the activity log data, including non-unicast pushes. The series begins with the earliest time given in which the group of pushes were sent. [Jump to examples ↓](#getactivitylogreport-examples) ### `GET /api/reports/activity/details` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `limit` | `integer` | | Number of results to return per request. Defaults to 100. Results paginate if requesting narrow precision over a long period of time. Min: 1 | **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/json;` - **`activities`** `array[object]` An array of activity log data. - **`app_key`** `string` The app key for the application. - **`end`** `string` The end [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for the report. Format: `date-time` - **`limit`** `integer` The optional limit for the number of entries to return per request. Defaults to 100. - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`start`** `string` The start [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for the report. Format: `date-time` **Examples** *Example (response truncated)* ```http GET /api/reports/activity/details?start=2020-06-02T20:47:20&end=2023-01-31T20:47:20 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "app_key": "Wz9d8TlSWk0lZTAwzHA2qc", "start": "2020-06-02T20:47:20", "end": "2023-01-31T20:47:20", "limit": 10, "next_page": "https://go.urbanairship.com/api/reports/activity/details...", "activities": [ { "push_id": "ecb8eaf0-0430-4dfa-93d8-c3149f479d96", "timestamp": "2023-01-31 20:47:20", "type": "GROUP", "experiment": true, "details": { "interaction": { "web": { "clicks": 20, "sessions": 13 }, "app": { "influenced": 13, "direct": 12, "indirect": 10, "rich_read": 5 } }, "delivery": { "web": { "total": 13 }, "app": { "silent": 125, "alerting": 13, "rich": 5, "in_app": { "impressions": 10, "impressions_opted_in": 5, "impressions_opted_out": 5 } } } } } ] } ``` --- ## App opens report {#getappopensreport} Get the number of users who have opened your app within the specified time period. [Jump to examples ↓](#getappopensreport-examples) ### `GET /api/reports/opens` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `precision` | `string` | Required | Granularity of results to return. Defaults to `DAILY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Default: `DAILY` | **Responses** **`200`** Returned on success, with the JSON representation of the app opens in the body of the response. Response body: **Content-Type:** `application/json;` - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`opens`** `array[object]` An array of App opens objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/opens?start=2020-08-01T10:00&end=2020-08-15T20:00&precision=MONTHLY HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "opens": [ { "date": "2020-08-01 00:00:00", "ios": 350, "android": 250 } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PlatformStatsRequest request = PlatformStatsRequest.newRequest(PlatformStatsRequestType.APP_OPENS) .setStart(DateTime.parse("2020-08-01T10:34:22Z")) .setEnd(DateTime.parse("2020-08-15T10:34:22Z")) .setPrecision(Precision.MONTHLY); Response response = client.execute(request); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, AppOpensList ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 8, 1) end_date = datetime(2020, 8, 15) for open in AppOpensList(airship=client, start_date=start_date, end_date=end_date, precision='DAILY'): print(open) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') listing = UA::AppOpensList.new( client: airship, start_date: '2020-08-01', end_date: '2020-08-15', precision: 'MONTHLY') listing.each do |app_opens| puts(app_opens) end ``` --- ## Custom Events detail listing {#getcustomeventsreport} Get a summary of Custom Event counts and values, by Custom Event, within the specified time period. [Jump to examples ↓](#getcustomeventsreport-examples) ### `GET /api/reports/events` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `precision` | `string` | | Granularity of results to return. Defaults to `DAILY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Default: `DAILY` | | `page` | `integer` | | Identifies the desired page number. Defaults to 1. If page is given a negative or out of bounds value, the default value will be used. | | `page_size` | `integer` | | Specifies how many results to return per page. Has a default value of 25 and a maximum value of 100. | **Responses** **`200`** Returned on success, with the JSON representation of the events in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`events`** `array[object]` An array of Custom Events and its details. - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`ok`** `boolean` Success. - **`prev_page`** `string` Link to the previous page, if available. Format: `url` - **`total_count`** `integer` Sum of all the count fields in the above array. Example: `12` - **`total_value`** `integer` Sum of all the value fields in the above array. Example: `321.2` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/events?start=2020-08-01T10:00:00.000Z&end=2020-08-15T20:00:00.000Z&precision=MONTHLY&page_size=20 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "total_value": 2, "total_count": 709, "next_page": "https://go.urbanairship.com/api/reports/events?start=2020-08-01T10:00:00.000Z&end=2020-08-15T20:00:00.000Z&precision=MONTHLY&page_size=20&page=2", "events": [ { "name": "banner_image", "conversion": "indirect", "location": "ua_mcrap", "count": 1, "value": 1 }, { "name": "bounce", "conversion": "direct", "location": "custom", "count": 23, "value": 0 }, { "name": "button-click-Do it ", "conversion": "direct", "location": "in_app_message", "count": 1, "value": 0 }, { "name": "button-click-Get Notifications", "conversion": "unattributed", "location": "in_app_message", "count": 3, "value": 0 }, { "name": "button-click-RATE NOW", "conversion": "direct", "location": "in_app_message", "count": 1, "value": 0 }, { "name": "button-click-Rate the app.", "conversion": "direct", "location": "in_app_message", "count": 1, "value": 0 } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); DateTime startDate = DateTime.parse("2022-01-01T10:00:00"); DateTime endDate = DateTime.parse("2023-01-01T10:00:00"); CustomEventsDetailsListingRequest customEventsDetailsListingRequest = CustomEventsDetailsListingRequest .newRequest(startDate, endDate) .setPageSize(10) .setPrecision(Precision.MONTHLY) .setPage(2); Response response = client.execute(customEventsDetailsListingRequest); List customEventsDetailResponses = response.getBody().get().getEvents().get(); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, CustomEventsList ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 8, 1) end_date = datetime(2020, 8, 15) for event in CustomEventsList(airship=client, start_date=start_date, end_date=end_date, precision='MONTHLY'): print(event) ``` --- ## Custom Events per group summary {#getcustomeventspergroupsummary} Get a summary of Custom Event counts and values associated with the provided Push ID. Includes all Custom Events from the time of the push up to current time. [Jump to examples ↓](#getcustomeventspergroupsummary-examples) ### `GET /api/reports/events/summary/pergroup/{group_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `group_id` | `string` | Required | The UUID for the requested group push ID. | **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `variant` | `integer` | | Variant number (0 to 25), or -1 for control events. | | `page` | `integer` | | Identifies the desired page number. Defaults to 1. If page is given a negative or out of bounds value, the default value will be used. | | `page_size` | `integer` | | Specifies how many results to return per page. Has a default value of 25 and a maximum value of 100. | **Responses** **`200`** Returned on success, with the JSON representation of the events in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` **All of:** - **`group_id`** `string` The UUID representing a specific group push. Format: `uuid` - **`events`** `array[object]` An array of Custom Events and its details. - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Will only be present if there are successive pages. Format: `url` - **`ok`** `boolean` Success. - **`prev_page`** `string` Link to the previous page, if available. Will only be present if there are preceding pages. Format: `url` - **`total_count`** `integer` Sum of all the count fields in the above array. Example: `12` - **`total_value`** `integer` Sum of all the value fields in the above array. Example: `321.2` - **`variant`** `integer` Variant number (0 to 25) or -1 for control events. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example request* ```http GET /api/reports/events/summary/pergroup/8bd09679-f672-4783-a31a-d4e516f9e99c HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` *Response with Group ID parameter* ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "group_id": "8bd09679-f672-4783-a31a-d4e516f9e99c", "events": [ { "name": "custom_event_name", "location": "custom", "conversion": "direct", "count": 4, "value": 16.4 }, ... ], "total_count": 12, "total_value": 321.2, "next_page": "https://go.urbanairship.com/api/reports/events/summary/pergroup/...", "prev_page": "https://go.urbanairship.com/api/reports/events/summary/pergroup/..." } ``` --- ## Custom Events per push summary {#getcustomeventsperpushsummary} Get a summary of Custom Event counts and values associated with the provided Push ID. Includes all Custom Events from the time of the push up to current time. [Jump to examples ↓](#getcustomeventsperpushsummary-examples) ### `GET /api/reports/events/summary/perpush/{push_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `push_id` | `string` | Required | The UUID for the requested push. | **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `variant` | `integer` | | Variant number (0 to 25), or -1 for control events. | | `page` | `integer` | | Identifies the desired page number. Defaults to 1. If page is given a negative or out of bounds value, the default value will be used. | | `page_size` | `integer` | | Specifies how many results to return per page. Has a default value of 25 and a maximum value of 100. | **Responses** **`200`** Returned on success, with the JSON representation of the events in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` **All of:** - **`push_id`** `string` The UUID representing a specific push. Format: `uuid` - **`events`** `array[object]` An array of Custom Events and its details. - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Will only be present if there are successive pages. Format: `url` - **`ok`** `boolean` Success. - **`prev_page`** `string` Link to the previous page, if available. Will only be present if there are preceding pages. Format: `url` - **`total_count`** `integer` Sum of all the count fields in the above array. Example: `12` - **`total_value`** `integer` Sum of all the value fields in the above array. Example: `321.2` - **`variant`** `integer` Variant number (0 to 25) or -1 for control events. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example request* ```http GET /api/reports/events/summary/perpush/8bd09679-f672-4783-a31a-d4e516f9e99c HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` *Response with Push ID parameter* ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "push_id": "8bd09679-f672-4783-a31a-d4e516f9e99c", "events": [ { "name": "custom_event_name", "location": "custom", "conversion": "direct", "count": 4, "value": 16.4 }, ... ], "total_count": 12, "total_value": 321.2, "next_page": "https://go.urbanairship.com/api/reports/events/summary/perpush/...", "prev_page": "https://go.urbanairship.com/api/reports/events/summary/perpush/..." } ``` *Response with variant parameter* ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "push_id": "8bd09679-f672-4783-a31a-d4e516f9e99c", "variant": 1, "events": [ { "name": "custom_event_name", "location": "custom", "conversion": "direct", "count": 4, "value": 16.4 }, ... ], "total_count": 12, "total_value": 321.2, "next_page": "https://go.urbanairship.com/api/reports/events/summary/perpush/...", "prev_page": "https://go.urbanairship.com/api/reports/events/summary/perpush/..." } ``` --- ## Devices report {#getdevicesreport} Get an app's opted-in and installed device counts by device type. [Jump to examples ↓](#getdevicesreport-examples) ### `GET /api/reports/devices` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `date` | `string` | Required | All device events counted occurred before this [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format). | **Responses** **`200`** Returned on success, with the JSON representation of the device counts in the body of the response. Response body: **Content-Type:** `application/json;` - **`counts`** `object` The counts for each device type. **OBJECT PROPERTIES** - **`amazon`** `object` The count object for a device type. **OBJECT PROPERTIES** - **`opted_in`** `integer` Opted in to receiving push notifications. Example: `140` - **`opted_out`** `integer` Opted out of receiving push notifications. Example: `89` - **`uninstalled`** `integer` Devices for which Reports has seen an uninstall event. Example: `9` - **`unique_devices`** `integer` Devices considered by Airship Reports to have the app installed. Example: `229` - **`android`** `object` The count object for a device type. **OBJECT PROPERTIES** - **`opted_in`** `integer` Opted in to receiving push notifications. Example: `140` - **`opted_out`** `integer` Opted out of receiving push notifications. Example: `89` - **`uninstalled`** `integer` Devices for which Reports has seen an uninstall event. Example: `9` - **`unique_devices`** `integer` Devices considered by Airship Reports to have the app installed. Example: `229` - **`ios`** `object` The count object for a device type. **OBJECT PROPERTIES** - **`opted_in`** `integer` Opted in to receiving push notifications. Example: `140` - **`opted_out`** `integer` Opted out of receiving push notifications. Example: `89` - **`uninstalled`** `integer` Devices for which Reports has seen an uninstall event. Example: `9` - **`unique_devices`** `integer` Devices considered by Airship Reports to have the app installed. Example: `229` - **`date_closed`** `string` All device events counted occurred before this [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format). Format: `date-time` Example: `2018-06-06 11:47:51` - **`date_computed`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) the device event data was tallied and stored. Format: `date-time` Example: `2018-06-07 11:47:51` - **`total_unique_devices`** `integer` Sum of the unique devices for every device type. Example: `12545` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/devices?date=2020-08-28T00:00:00 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "total_unique_devices": 13186, "date_closed": "2020-08-28 00:00:00", "date_computed": "2020-08-29 13:30:45", "counts": { "ios": { "unique_devices": 231, "opted_in": 142, "opted_out": 89, "uninstalled": 2096 }, "android": { "unique_devices": 11795, "opted_in": 226, "opted_out": 11569, "uninstalled": 1069 }, "amazon": { "unique_devices": 29, "opted_in": 22, "opted_out": 7, "uninstalled": 9 }, "sms": { "unique_devices": 26, "opted_in": 23, "opted_out": 3, "uninstalled": 17 } } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); DevicesReportRequest request = DevicesReportRequest.newRequest() .setDate(DateTime.parse("2020-08-28T10:34:22Z")); Response response = client.execute(request); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, DevicesReport ) client = BasicAuthClient( key='', secret='' ) date = datetime(2020, 8, 28) response = DevicesReport(airship=client).get(date=date) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') d = UA::DevicesReport.new(client: airship) devices = d.get(date: '2020/08/28') ``` --- ## Experiment overview report {#getexperimentoverviewreport} Returns statistics and metadata about an experiment (A/B Test). [Jump to examples ↓](#getexperimentoverviewreport-examples) ### `GET /api/reports/experiment/overview/{push_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `push_id` | `string` | Required | The `push_id` of the requested experiment. | **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/json;` - **`app_key`** `string` The app key for the given `push_id`. - **`control`** `object` JSON object describing the control group, i.e., those devices that receive no notification, for the experiment. **OBJECT PROPERTIES** - **`audience_pct`** `number` The percentage of the total audience belonging to the control group. - **`response_rate_pct`** `number` The response rate from the control group. - **`responses`** `integer` The number of responses from the control group. Example: `123` - **`sends`** `integer` The number of pushes sent to native mobile platforms, e.g., iOS. Exclusive of `open_channel_sends`, which are broken out under `open_channel_sends`. Example: `123` - **`direct_responses`** `integer` The number of direct responses to the experiment. - **`experiment_id`** `string` ID for the requested experiment. Format: `uuid` - **`influenced_responses`** `integer` The number of influenced responses to the experiment. - **`variants`** `object` Single variant reporting object or array of variant reporting objects, including associated metadata, audience percentage and response statistics. **OBJECT PROPERTIES** - **`audience_pct`** `number` - **`direct_response_pct`** `number` The percentage direct responses to the notification measured by the SDK. Example: `13.44` - **`direct_responses`** `integer` The number of direct responses to the variant measured by the SDK. Example: `45` - **`id`** `integer` - **`indirect_response_pct`** `number` The percentage indirect responses to the notification measured by the SDK. Example: `0` - **`indirect_responses`** `integer` The number of indirect responses to the variant measured by the SDK. Example: `0` - **`name`** `string` - **`sends`** `integer` The number of pushes sent SDK-supporting platforms, e.g., iOS, Android, and Web. Exclusive of `open_channel_sends`, which are broken out under `open_channel_sends`. Example: `123` - **`web_clicks`** `integer` The number of web notifications that the audience clicked on. - **`web_sessions`** `integer` The total number of web sessions that resulted in a notification. Use in conjunction with `web_clicks` to determine the effectiveness of your web notification experiments. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/experiment/overview/b43ae1b2-3ff6-4c02-adb2-79deac0bbb19 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "app_key": "some_app_key", "experiment_id": "a7806815-6483-4cb9-9d74-bc3b4f3dc1b8", "push_id": "b43ae1b2-3ff6-4c02-adb2-79deac0bbb19", "created": "2020-02-25 23:03:12", "sends": 532, "direct_responses": 50, "influenced_responses": 60, "web_clicks": 6, "web_sessions": 8, "variants": [ { "id" : 0, "name": "call to action", "audience_pct": 45.0, "sends": 238, "direct_responses": 32, "direct_response_pct": 13.44, "indirect_responses": 0, "indirect_response_pct": 0.0 }, { "id" : 1, "name": "gentle reminder", "audience_pct": 45.0, "sends": 251, "direct_responses": 20, "direct_response_pct": 7.97, "indirect_responses": 4, "indirect_response_pct": 1.59 } ], "control": { "audience_pct": 10.0, "sends": 50, "responses": 1, "response_rate_pct": 2.0 } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ExperimentOverviewReportRequest experimentOverviewReportRequest = ExperimentOverviewReportRequest.newRequest("4b83d756-cc64-45e0-b140-3f5ec04170fb"); Response response = client.execute(experimentOverviewReportRequest); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, ExperimentReport ) client = BasicAuthClient( key='', secret='' ) experiment_report = ExperimentReport(airship=client) overview_report = experiment_report.get_overview( push_id="b43ae1b2-3ff6-4c02-adb2-79deac0bbb19" ) print(overview_report) ``` --- ## Experiment variant report {#getexperimentvariantreport} Returns statistics and metadata about a specific variant in an experiment (A/B Test). [Jump to examples ↓](#getexperimentvariantreport-examples) ### `GET /api/reports/experiment/detail/{push_id}/{variant_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `push_id` | `string` | Required | The `push_id` of the requested experiment. | | `variant_id` | `integer` | Required | The specific variant you want to return results for. Min: 1 Max: 26 | **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/json;` - **`app_key`** `string` The app key for the given `push_id`. - **`created`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the variant was created. Format: `date-time` Read only: true - **`direct_responses`** `integer` The number of direct responses to the variant. - **`experiment_id`** `string` ID of the experiment that the variant belongs to. Format: `uuid` - **`influenced_responses`** `integer` The total number of influenced responses to the variant. - **`platforms`** `object` **OBJECT PROPERTIES** - **`amazon`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the variant notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members that accounted the variant on the specified platform. - **`android`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the variant notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members that accounted the variant on the specified platform. - **`ios`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the variant notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members that accounted the variant on the specified platform. - **`web`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the variant notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members that accounted the variant on the specified platform. - **`push_id`** `string` The specific push_id that the variant belonged to. Format: `uuid` - **`variant`** `integer` The individual variant you want to return results for. Variants are ordered 1-26 in the order that they are arranged in the `variants` array when you created the experiment. Min: 1, Max: 26 - **`variant_name`** `string` The name of the variant specified in the endpoint. **Examples** *Example* ```http GET /api/reports/experiment/detail/b43ae1b2-3ff6-4c02-adb2-79deac0bbb19/2 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "app_key": "some_app_key", "experiment_id": "a7806815-6483-4cb9-9d74-bc3b4f3dc1b8", "push_id": "b43ae1b2-3ff6-4c02-adb2-79deac0bbb19", "created": "2020-02-25 23:03:12", "variant": 2, "variant_name": "thing_two", "sends": 64, "direct_responses": 3, "influenced_responses": 1, "platforms": { "android": { "direct_responses": 0, "influenced_responses": 0, "sends": 22 }, "ios": { "direct_responses": 0, "influenced_responses": 1, "sends": 36 }, "amazon": { "direct_responses": 0, "influenced_responses": 0, "sends": 0 }, "web": { "direct_responses": 3, "indirect_responses": 0, "sends": 6 } } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ExperimentVariantReportRequest experimentVariantReportRequest = ExperimentVariantReportRequest.newRequest("b43ae1b2-3ff6-4c02-adb2-79deac0bbb19", "1"); Response response = client.execute(experimentVariantReportRequest); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, ExperimentReport ) client = BasicAuthClient( key='', secret='' ) experiment_report = ExperimentReport(airship=client) variant_report = experiment_report.get_variant( push_id="b43ae1b2-3ff6-4c02-adb2-79deac0bbb19", variant=2 ) print(variant_report) ``` --- ## Individual push response statistics {#getresponsesforpush} Returns detailed reports information about a specific push notification. Use the `push_id`, which is the identifier returned by the API that represents a specific push message delivery. [Jump to examples ↓](#getresponsesforpush-examples) ### `GET /api/reports/responses/{push_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `push_id` | `string` | Required | The UUID for the requested push. | **Responses** **`200`** Returned on success, with the JSON representation of the push statistics in the body of the response. Response body: **Content-Type:** `application/json;` - **`direct_responses`** `integer` The number of native-platform direct responses to the notification measured by the SDK. Example: `45` - **`open_channels_sends`** `object` Contains an array of the number of send counts per open platform. If there were no open channels sends associated with the push ID, an empty result will be returned. **OBJECT PROPERTIES** - **`platforms`** `array[object]` An array of objects indicating the total sends by open platform. - **`push_time`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) indicating the time that the push was initially sent. Format: `date-time` Example: `2018-06-02 10:00:00` - **`push_type`** `string` This string describes the push operation, which is often comparable to the audience selection. Possible values: `BROADCAST_PUSH`, `TAG_PUSH`, `SCHEDULED_PUSH`, `SEGMENTS_PUSH`, `UNICAST_PUSH` Example: `TAG_PUSH` - **`push_uuid`** `string` The UUID for the requested push. Format: `uuid` Example: `f133a7c8-d750-11e1-a6cf-e06995b6c872` - **`sends`** `integer` The number of pushes sent to native mobile platforms, e.g., iOS. Exclusive of `open_channel_sends`, which are broken out under `open_channel_sends`. Example: `123` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/responses/90f28bc6-6c9b-4c99-b970-973afc266e08 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "push_uuid": "90f28bc6-6c9b-4c99-b970-973afc266e08", "push_time": "2020-02-25 23:03:12", "push_type": "UNICAST_PUSH", "sends": 167, "direct_responses": 15, "open_channels_sends": { "platforms": [ { "id": "PLATFORM_NAME", "sends": 22 }, { "id": "ANOTHER_PLATFORM", "sends": 145 } ] } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PushInfoRequest request = PushInfoRequest.newRequest("90f28bc6-6c9b-4c99-b970-973afc266e08"); Response response = client.execute(request); PushInfoResponse pushInfo = response.getBody().get(); // Number of sends int sends = pushInfo.getSends(); // Number of direct responses to the push int directResponses = pushInfo.getDirectResponses(); // When the push was sent DateTime date = pushInfo.getPushTime(); // The push type - can be one of BROADCAST_PUSH, SCHEDULED_PUSH, TAG_PUSH, UNICAST_PUSH PushInfoResponse.PushType type = pushInfo.getPushType(); // The unique identifier for the push UUID pushId = pushInfo.getPushId(); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, IndividualResponseStats ) client = BasicAuthClient( key='', secret='' ) push_id = '90f28bc6-6c9b-4c99-b970-973afc266e08' response = IndividualResponseStats(airship=client).get(push_id) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') d = UA::IndividualResponseStats.new(client: airship) statistics = d.get(push_id: '90f28bc6-6c9b-4c99-b970-973afc266e08') ``` --- ## Opt-in report {#getoptinreport} Get the number of opted-in Push users who access the app within the specified time period. [Jump to examples ↓](#getoptinreport-examples) ### `GET /api/reports/optins` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `precision` | `string` | Required | Granularity of results to return. Defaults to `DAILY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Default: `DAILY` | **Responses** **`200`** Returned on success, with the JSON representation of the opt-ins in the body of the response. Response body: **Content-Type:** `application/json;` - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`optins`** `array[object]` An array of OptIn objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/optins?start=2020-08-01T10:00&end=2020-08-15T20:00&precision=MONTHLY HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "optins": [ { "android": 50, "date": "2020-05-01 00:00:00", "ios": 500 } ], "next_page": "https://go.urbanairship.com/api/reports/..." } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PlatformStatsRequest request = PlatformStatsRequest.newRequest(PlatformStatsRequestType.OPT_INS) .setStart(DateTime.parse("2020-08-01T10:34:22Z")) .setEnd(DateTime.parse("2020-08-15T10:34:22Z")) .setPrecision(Precision.MONTHLY); Response response = client.execute(request); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, OptInList ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 8, 1) end_date = datetime(2020, 8, 15) for opt_in in OptInList(airship=client, start_date=start_date, end_date=end_date, precision='DAILY'): print(opt_in) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') listing = UA::OptInList.new( client: airship, start_date: '2020-08-01', end_date: '2020-08-15', precision: 'MONTHLY') listing.each do |opt_ins| puts(opt_ins) end ``` --- ## Opt-out report {#getoptoutreport} Get the number of opted-out Push users who access the app within the specified time period. [Jump to examples ↓](#getoptoutreport-examples) ### `GET /api/reports/optouts` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `precision` | `string` | Required | Granularity of results to return. Defaults to `DAILY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Default: `DAILY` | **Responses** **`200`** Returned on success, with the JSON representation of the opt-outs in the body of the response. Response body: **Content-Type:** `application/json;` - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`optouts`** `array[object]` An array of OptOut objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/optouts?start=2020-08-01T10:00&end=2020-08-15T20:00&precision=MONTHLY HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "optouts": [ { "android": 5, "date": "2020-05-01 00:00:00", "ios": 25 } ], "next_page": "https://go.urbanairship.com/api/reports/..." } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PlatformStatsRequest request = PlatformStatsRequest.newRequest(PlatformStatsRequestType.OPT_OUTS) .setStart(DateTime.parse("2020-08-01T10:34:22Z")) .setEnd(DateTime.parse("2020-08-15T10:34:22Z")) .setPrecision(Precision.MONTHLY); Response response = client.execute(request); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, OptOutList ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 8, 1) end_date = datetime(2020, 8, 15) for opt_out in OptOutList(airship=client, start_date=start_date, end_date=end_date, precision='DAILY'): print(opt_out) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') listing = UA::OptOutList.new( client: airship, start_date: '2020-08-01', end_date: '2020-08-15', precision: 'MONTHLY') listing.each do |opt_outs| puts(opt_outs) end ``` --- ## Per group push detail report {#getpergrouppushdetailreport} Returns statistics and other information for a given group push message. [Jump to examples ↓](#getpergrouppushdetailreport-examples) ### `GET /api/reports/pergroup/detail/{group_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `group_id` | `string` | Required | The `group_id` of the requested report. | **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/json;` **All of:** - **`group_id`** `string` The UUID representing a specific group push. Format: `uuid` - **`alerting_sends`** `integer` The number of alerting sends. - **`app_key`** `string` The app key for the given push. - **`created`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the push was created. Format: `date-time` Read only: true - **`direct_responses`** `integer` The number of direct responses. - **`influenced_responses`** `integer` The total number of influenced responses. - **`platforms`** `object` **OBJECT PROPERTIES** - **`amazon`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members accounted on the specified platform. - **`android`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members accounted on the specified platform. - **`ios`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members accounted on the specified platform. - **`web`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members accounted on the specified platform. - **`rich_deletions`** `integer` The number of rich deletions. - **`rich_responses`** `integer` The number of rich responses. - **`rich_sends`** `integer` The number of rich sends. - **`sends`** `integer` The number of pushes sent. - **`silent_sends`** `integer` The number of silent sends. **Examples** *Example* ```http GET /api/reports/pergroup/detail/57ef3728-79dc-46b1-a6b9-20081e561f97 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "app_key": "some_app_key", "group_id": "57ef3728-79dc-46b1-a6b9-20081e561f97", "created": "2023-07-25 23:03:12", "rich_deletions": 0, "rich_responses": 0, "rich_sends": 0, "sends": 103, "alerting_sends": 103, "silent_sends": 0, "direct_responses": 0, "influenced_responses": 3, "platforms": { "android": { "direct_responses": 0, "influenced_responses": 0, "sends": 22 }, "ios": { "direct_responses": 0, "influenced_responses": 1, "sends": 36 }, "amazon": { "direct_responses": 0, "influenced_responses": 1, "sends": 5 }, "web": { "direct_responses": 0, "influenced_responses": 1, "sends": 40 } } } ``` --- ## Per group push time series report {#getpergrouppushtimeseriesreport} Returns the default time series data (hourly precision for 12 hours) for a given group push message. The series begins with the hour in which the push was sent. By specifying the precision without providing a time range, the default number of periods at each precision returned are as follows: Hourly: 12, Daily: 7, Monthly: 3. Results paginate if requesting narrow precision over a long period of time. [Jump to examples ↓](#getpergrouppushtimeseriesreport-examples) ### `GET /api/reports/pergroup/series/{group_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `group_id` | `string` | Required | The `group_id` of the requested report. | **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `precision` | `string` | | The precision of the report. Defaults to `HOURLY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` | | `start` | `string` | | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/json;` **All of:** - **`group_id`** `string` The UUID representing a specific group push. Format: `uuid` - **`app_key`** `string` The app key for the application. Example: `your_app_key` - **`end`** `string` The end [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for the report. Format: `date-time` Example: `2018-06-02 10:00:00` - **`precision`** `string` The precision of the report. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Example: `HOURLY` - **`start`** `string` The start [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for the report. Format: `date-time` Example: `2018-06-01 10:00:00` - **`counts`** `array[object]` Array of total count objects, each representing counts within the given [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) range and precision. **Examples** *Example (response truncated to 2 items)* ```http GET /api/reports/pergroup/series/57ef3728-79dc-46b1-a6b9-20081e561f97 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "app_key": "some_app_key", "group_id": "57ef3728-79dc-46b1-a6b9-20081e561f97", "start": "2023-07-25 23:00:00", "end": "2023-07-26 11:00:00", "precision": "HOURLY", "counts": [ { "push_platforms": { "all": { "direct_responses": 0, "influenced_responses": 1, "sends": 58 }, "android": { "direct_responses": 0, "influenced_responses": 0, "sends": 22 }, "ios": { "direct_responses": 0, "influenced_responses": 1, "sends": 36 } }, "rich_push_platforms": { "all": { "responses": 0, "sends": 0 } }, "time": "2023-07-25 23:00:00" }, { "push_platforms": { "all": { "direct_responses": 0, "influenced_responses": 0, "sends": 0 }, "android": { "direct_responses": 0, "influenced_responses": 0, "sends": 0 }, "ios": { "direct_responses": 0, "influenced_responses": 0, "sends": 0 } }, "rich_push_platforms": { "all": { "responses": 0, "sends": 0 } }, "time": "2023-07-26 00:00:00" } ] } ``` --- ## Per push detail report {#getperpushdetailreport} Returns statistics and other information for a given push message. [Jump to examples ↓](#getperpushdetailreport-examples) ### `GET /api/reports/perpush/detail/{push_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `push_id` | `string` | Required | The `push_id` of the requested report. | **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/json;` **All of:** - **`push_id`** `string` The UUID representing a specific push. Format: `uuid` - **`alerting_sends`** `integer` The number of alerting sends. - **`app_key`** `string` The app key for the given push. - **`created`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the push was created. Format: `date-time` Read only: true - **`direct_responses`** `integer` The number of direct responses. - **`influenced_responses`** `integer` The total number of influenced responses. - **`platforms`** `object` **OBJECT PROPERTIES** - **`amazon`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members accounted on the specified platform. - **`android`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members accounted on the specified platform. - **`ios`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members accounted on the specified platform. - **`web`** `object` **OBJECT PROPERTIES** - **`direct_responses`** `integer` The number of direct responses (clicks/app opens) to the notification on this platform as measured by the SDK. - **`influenced_responses`** `integer` The number of opens or clicks resulting from your notification (directly or indirectly). - **`sends`** `integer` The total number of audience members accounted on the specified platform. - **`rich_deletions`** `integer` The number of rich deletions. - **`rich_responses`** `integer` The number of rich responses. - **`rich_sends`** `integer` The number of rich sends. - **`sends`** `integer` The number of pushes sent. - **`silent_sends`** `integer` The number of silent sends. **Examples** *Example* ```http GET /api/reports/perpush/detail/57ef3728-79dc-46b1-a6b9-20081e561f97 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "app_key": "some_app_key", "push_id": "57ef3728-79dc-46b1-a6b9-20081e561f97", "created": "2023-07-25 23:03:12", "rich_deletions": 0, "rich_responses": 0, "rich_sends": 0, "sends": 103, "alerting_sends": 103, "silent_sends": 0, "direct_responses": 0, "influenced_responses": 3, "platforms": { "android": { "direct_responses": 0, "influenced_responses": 0, "sends": 22 }, "ios": { "direct_responses": 0, "influenced_responses": 1, "sends": 36 }, "amazon": { "direct_responses": 0, "influenced_responses": 1, "sends": 5 }, "web": { "direct_responses": 0, "influenced_responses": 1, "sends": 40 } } } ``` --- ## Per push time series report {#getperpushtimeseriesreport} Returns the default time series data (hourly precision for 12 hours) for a given push message. The series begins with the hour in which the push was sent. By specifying the precision without providing a time range, the default number of periods at each precision returned are as follows: Hourly: 12, Daily: 7, Monthly: 3. Results paginate if requesting narrow precision over a long period of time. [Jump to examples ↓](#getperpushtimeseriesreport-examples) ### `GET /api/reports/perpush/series/{push_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `push_id` | `string` | Required | The `push_id` of the requested report. | **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `precision` | `string` | | The precision of the report. Defaults to `HOURLY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` | | `start` | `string` | | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/json;` **All of:** - **`push_id`** `string` The UUID representing a specific push. Format: `uuid` - **`app_key`** `string` The app key for the application. Example: `your_app_key` - **`end`** `string` The end [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for the report. Format: `date-time` Example: `2018-06-02 10:00:00` - **`precision`** `string` The precision of the report. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Example: `HOURLY` - **`start`** `string` The start [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for the report. Format: `date-time` Example: `2018-06-01 10:00:00` - **`counts`** `array[object]` Array of total count objects, each representing counts within the given [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) range and precision. **Examples** *Example (response truncated to 2 items)* ```http GET /api/reports/perpush/series/57ef3728-79dc-46b1-a6b9-20081e561f97 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "app_key": "some_app_key", "push_id": "57ef3728-79dc-46b1-a6b9-20081e561f97", "start": "2023-07-25 23:00:00", "end": "2023-07-26 11:00:00", "precision": "HOURLY", "counts": [ { "push_platforms": { "all": { "direct_responses": 0, "influenced_responses": 1, "sends": 58 }, "android": { "direct_responses": 0, "influenced_responses": 0, "sends": 22 }, "ios": { "direct_responses": 0, "influenced_responses": 1, "sends": 36 } }, "rich_push_platforms": { "all": { "responses": 0, "sends": 0 } }, "time": "2023-07-25 23:00:00" }, { "push_platforms": { "all": { "direct_responses": 0, "influenced_responses": 0, "sends": 0 }, "android": { "direct_responses": 0, "influenced_responses": 0, "sends": 0 }, "ios": { "direct_responses": 0, "influenced_responses": 0, "sends": 0 } }, "rich_push_platforms": { "all": { "responses": 0, "sends": 0 } }, "time": "2023-07-26 00:00:00" } ] } ``` --- ## Push body per push {#getpushbodyperpush} Returns the push body for the given push message. [Jump to examples ↓](#getpushbodyperpush-examples) ### `GET /api/reports/perpush/pushbody/{push_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `push_id` | `string` | Required | The `push_id` of the requested push body. | **Responses** **`200`** Returned on success. Response body: **Content-Type:** `application/json;` - **`push_body`** `string` The push body as a base64 encoded JSON value. **Examples** *Example* ```http GET /api/reports/perpush/pushbody/57ef3728-79dc-46b1-a6b9-20081e561f97 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "push_body": "" } ``` --- ## Push report {#getpushreport} Get the number of pushes you have sent within a specified time period. [Jump to examples ↓](#getpushreport-examples) ### `GET /api/reports/sends` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `precision` | `string` | Required | Granularity of results to return. Defaults to `DAILY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Default: `DAILY` | **Responses** **`200`** Returned on success, with the JSON representation of the sends in the body of the response. Response body: **Content-Type:** `application/json;` - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`sends`** `array[object]` An array of send objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/sends?start=2020-05-01T10:00&end=2020-05-30T20:00&precision=MONTHLY HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "sends": [ { "android": 50, "date": "2020-05-01 00:00:00", "ios": 500 } ], "next_page": "https://go.urbanairship.com/api/reports/..." } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PlatformStatsRequest request = PlatformStatsRequest.newRequest(PlatformStatsRequestType.SENDS) .setStart(DateTime.parse("2020-05-01T10:34:22Z")) .setEnd(DateTime.parse("2020-05-30T10:34:22Z")) .setPrecision(Precision.MONTHLY); Response response = client.execute(request); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, PushList ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 5, 1) end_date = datetime(2020, 5, 30) precision = 'MONTHLY' listing = PushList(airship=client, start_date=start_date, end_date=end_date, precision=precision) for resp in listing: print(resp.date, resp.android, resp.ios) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') listing = UA::PushList.new( client: airship, start_date: '2020/05/01', end_date: '2020/05/30', precision: 'MONTHLY' ) listing.each do |resp| puts(resp) end ``` --- ## Response listing {#getresponses} Get a listing of all pushes, plus basic response information, for a given time period. Start and end date times are required parameters. The time defaults to 00:00 UTC if not specified. [Jump to examples ↓](#getresponses-examples) ### `GET /api/reports/responses/list` {{< note >}} If you don't specify a `start` and `end` time, the system assumes 00:00 UTC, which will provide results through the previous day. Use timestamps to get results for a specific time period. If only using the date, set it in the future to ensure you will see the most recent listing. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `limit` | `integer` | | Number of results to return at one time (for pagination). Min: 1 | **Responses** **`200`** Returned on success, with the JSON representation of the listing in the body of the response. Response body: **Content-Type:** `application/json;` - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`pushes`** `array[object]` An array of all pushes and its basic response information. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/responses/list?start=2020-08-01T10:00&end=2020-08-15T10:00&limit=20 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "next_page": "https://go.urbanairship.com/api/reports/responses/list?start=2020-08-01+10%...", "pushes": [ { "push_uuid": "f4db3752-a982-4a2b-994e-7b5fd1c7f02f", "push_time": "2020-08-15 02:12:22", "push_type": "UNICAST_PUSH", "group_id": "4e768dc7-4ebc-4206-890a-60b5627763a7", "direct_responses": 0, "sends": 1, "open_channels_sends": { "platforms": [] } }, { "push_uuid": "5a4ade58-fbd3-43a2-ac3c-e834ee190151", "push_time": "2020-08-14 19:58:15", "push_type": "UNICAST_PUSH", "group_id": "c5664e1f-106e-4616-9820-7d9ecce8a3f3", "direct_responses": 1, "sends": 2, "open_channels_sends": { "platforms": [] } } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PushListingRequest request = PushListingRequest.newRequest() .setStart(DateTime.parse("2020-08-01T10:34:22Z")) .setEnd(DateTime.parse("2020-08-15T10:34:22Z")) .setLimit(20); Response response = client.execute(request); // Get the first item in an array of push info responses. You can use all of the getters // listed in the "Individual Push Response Statistics" section. PushInfoResponse pushInfo = response.getBody().get().getPushInfoList().get().get(0); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, ResponseList ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 8, 1) end_date = datetime(2020, 8, 15) for response in ResponseList(airship=client, start_date=start_date, end_date=end_date): print(response) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') response_list = UA::ResponseList.new( client: airship, start_date: '2020-08-01', end_date: '2020-08-30', limit: 20, push_id_start: 'start_id' ) response_list.each do |resp| puts(resp) end ``` --- ## Response report {#getresponsereport} Get the number of direct and influenced opens of your app. [Jump to examples ↓](#getresponsereport-examples) ### `GET /api/reports/responses` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `precision` | `string` | | Granularity of results to return. Defaults to `DAILY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Default: `DAILY` | **Responses** **`200`** Returned on success, with the JSON representation of the responses in the body of the response. Response body: **Content-Type:** `application/json;` - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`responses`** `array[object]` An array of response objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/responses?start=2020-05-01T10:00&end=2020-05-30T10:00&precision=MONTHLY HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "next_page": "https://go.urbanairship.com/api/reports/...", "responses": [ { "android": { "direct": 25, "influenced": 118 }, "date": "2020-05-01 00:00:00", "ios": { "direct": 16, "influenced": 87 } } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ResponseReportRequest request = ResponseReportRequest .newRequest(DateTime.parse("2020-05-01T10:34:22Z"), DateTime.parse("2020-05-30T10:34:22Z"), Precision.MONTHLY); Response response = client.execute(request); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, ResponseReportList ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 5, 1) end_date = datetime(2020, 5, 30) for response in ResponseReportList(airship=client, start_date=start_date, end_date=end_date, precision='DAILY'): print(response) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') listing = UA::ResponseReportList.new( client: airship, start_date: '2020-05-01', end_date: '2020-05-30', precision: 'MONTHLY' ) listing.each do |resp| puts(resp) end ``` --- ## Time in app report {#gettimeinappreport} Get the average amount of time users have spent in your app within the specified time period. [Jump to examples ↓](#gettimeinappreport-examples) ### `GET /api/reports/timeinapp` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `precision` | `string` | Required | Granularity of results to return. Defaults to `DAILY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Default: `DAILY` | **Responses** **`200`** Returned on success, with the JSON representation of the time in app in the body of the response. Response body: **Content-Type:** `application/json;` - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` - **`sends`** `array[object]` An array of TimeInApp objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/timeinapp?start=2020-05-01T10:00&end=2020-05-15T20:00&precision=MONTHLY HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "timeinapp": [ { "android": 50, "date": "2020-05-01 00:00:00", "ios": 500 } ], "next_page": "https://go.urbanairship.com/api/reports/..." } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); PlatformStatsRequest request = PlatformStatsRequest.newRequest(PlatformStatsRequestType.TIME_IN_APP) .setStart(DateTime.parse("2020-05-01T10:34:22Z")) .setEnd(DateTime.parse("2020-05-15T10:34:22Z")) .setPrecision(Precision.MONTHLY); Response response = client.execute(request); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, TimeInAppList ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 5, 1) end_date = datetime(2020, 5, 15) precision = 'MONTHLY' listing = TimeInAppList(airship=client, start_date=start_date, end_date=end_date, precision=precision) for resp in listing: print(resp.date, resp.android, resp.ios) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') listing = UA::TimeInAppList.new( client: airship, start_date: '2020-05-01', end_date: '2020-05-30', precision: 'MONTHLY') listing.each do |time_in_app| puts(time_in_app) end ``` --- ## Web response report {#getwebresponsereport} Get the web interaction data for the given app key. Accepts a required start time and optional end time and precision parameters. [Jump to examples ↓](#getwebresponsereport-examples) ### `GET /api/reports/web/interaction` {{< note >}} If you don't specify an `end` time, the system assumes 00:00 UTC, which will provide results through the previous day. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `app_key` | `string` | Required | The app key for your web project. | | `start` | `string` | Required | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for start of report. | | `end` | `string` | | A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for end of report. | | `precision` | `string` | | The precision of the report. Defaults to `HOURLY`. Possible values: `HOURLY`, `DAILY`, `MONTHLY` | **Responses** **`200`** Returned on success, with the JSON representation of the web data in the body of the response. Response body: **Content-Type:** `application/json;` **All of:** - **`app_key`** `string` The app key for the application. Example: `your_app_key` - **`end`** `string` The end [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for the report. Format: `date-time` Example: `2018-06-02 10:00:00` - **`precision`** `string` The precision of the report. Possible values: `HOURLY`, `DAILY`, `MONTHLY` Example: `HOURLY` - **`start`** `string` The start [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) for the report. Format: `date-time` Example: `2018-06-01 10:00:00` - **`total_counts`** `array[object]` Array of total count objects, each representing counts within the given [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) range and precision. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/reports/web/interaction?app_key=ZGIwZTY3YjEtZTRiMi00ZG&start=2020-05-01T10:00&end=2020-05-03T20:00&precision=HOURLY HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "app_key": "ZGIwZTY3YjEtZTRiMi00ZG", "end": "2020-05-03 00:00:00", "precision": "HOURLY", "start": "2020-05-01 00:00:00", "total_counts": [ {"counts": {"clicks": 36, "sessions": 55 }, "date": "2020-05-01 10:00:00"}, {"counts": {"clicks": 50, "sessions": 79 }, "date": "2020-05-01 11:00:00"}, {"..."}, {"..."}, {"counts": {"clicks": 67, "sessions": 75 }, "date": "2020-05-03 20:00:00"} ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); WebResponseReportRequest webResponseReportRequest = WebResponseReportRequest.newRequest("", DateTime.parse("2020-08-01T10:34:22Z")); Response response = client.execute(webResponseReportRequest); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, WebResponseReport ) client = BasicAuthClient( key='', secret='' ) start_date = datetime(2020, 5, 1) end_date = datetime(2020, 5, 3) for web_response in WebResponseReport(airship=client, start_date=start_date, end_date=end_date, precision='DAILY'): print(web_response) ``` --- # Schedules > Schedule notifications. {{< important >}} The API prohibits batch sizes of larger than 1,000 for scheduled pushes, and batches of larger than 100 for push to local time scheduled pushes. {{< /important >}} ## Delete schedule {#deleteschedule} Delete a schedule resource, which will result in no more pushes being sent. If the resource is successfully deleted, the response does not include a body. [Jump to examples ↓](#deleteschedule-examples) ### `DELETE /api/schedules/{schedule_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): sch **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `schedule_id` | `string` | Required | The ID of a schedule. | **Responses** **`204`** An API request was successful, but there is no response body to return. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http DELETE /api/schedules/b384ca54-0a1d-9cb3-2dfd-ae5964630e66 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 204 No Content ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ScheduleDeleteRequest request = ScheduleDeleteRequest.newRequest("b384ca54-0a1d-9cb3-2dfd-ae5964630e66"); Response response = client.execute(request); ``` ```python from urbanairship import BasicAuthClient, ScheduledPush client = BasicAuthClient( key='', secret='' ) schedule = ScheduledPush.from_url(client, 'https://go.urbanairship.com/api/schedules/b384ca54-0a1d-9cb3-2dfd-ae5964630e66') # Cancel schedule schedule.cancel() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') schedule = airship.create_scheduled_push schedule = UA::ScheduledPush.from_url(client: airship, url: 'https://go.urbanairship.com/api/schedules/b384ca54-0a1d-9cb3-2dfd-ae5964630e66') schedule.cancel ``` --- ## List a specific schedule {#getschedule} Fetch the current definition of a single schedule resource. Returns a single schedule object. [Jump to examples ↓](#getschedule-examples) ### `GET /api/schedules/{schedule_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): sch **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `schedule_id` | `string` | Required | The ID of a schedule. | **Responses** **`200`** Returned on success, with the JSON representation of the scheduled push in the body of the response. Response body: **Content-Type:** `application/json` [Schedule object]({{< ref "/developer/rest-api/ua/schemas/schedules/" >}}#scheduleobject) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/schedules/5cde3564-ead8-9743-63af-821e12337812 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "name": "I would like to subscribe to your newsletter", "schedule": { "scheduled_time": "2020-04-01T18:45:30" }, "push": { "audience": { "tag": [ "intriguing", "ideas" ] }, "notification": { "alert": "Check your inbox!" }, "device_types": [ "ios", "android" ] } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ScheduleListingRequest request = ScheduleListingRequest.newRequest("5cde3564-ead8-9743-63af-821e12337812"); Response response = client.execute(request); SchedulePayloadResponse schedule = response.getBody().get().getSchedules().get(0); // Get the schedule's name Optional name = schedule.getName(); // Get the push IDs Set pushIds = schedule.getPushIds(); // Get the scheduled time Schedule sched = schedule.getSchedule(); // Get the associated push payload PushPayload payload = schedule.getPushPayload(); // Get the URL Optional url = schedule.getUrl(); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') schedule = airship.create_scheduled_push scheduled_push = UA::ScheduledPush.new(airship) schedule_details = scheduled_push.list(schedule_id: '5cde3564-ead8-9743-63af-821e12337812') puts(schedule_details) ``` --- ## List schedules {#getschedules} List all existing schedules. Returns an array of schedule objects in the `schedules` attribute. [Jump to examples ↓](#getschedules-examples) ### `GET /api/schedules` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): sch **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `start` | `string` | | An optional string ID of the starting element for paginating results. | | `limit` | `integer` | | An optional integer as maximum number of elements to return. The default limit is 200 Schedule Objects per request. Set the limit to 200 or fewer in your API calls. | **Responses** **`200`** Returned on success, with the JSON representation of the scheduled pushes in the body of the response. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`count`** `integer` - **`next_page`** `string` There might be more than one page of results for this listing. Follow this URL if it is present to the next batch of results. Format: `url` Example: `https://go.urbanairship.com/api/schedules/?start=8bcb15a6-1f81-451a-95a1-05afd40e271c&limit=20` - **`ok`** `boolean` Success. - **`schedules`** `array` <[Schedule object]({{< ref "/developer/rest-api/ua/schemas/schedules/" >}}#scheduleobject)> An array of schedule objects. - **`total_count`** `integer` **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/schedules HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Count: 2 Data-Attribute: schedules Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "count": 2, "total_count": 4, "next_page": "https://go.urbanairship.com/api/schedules/?start=5c69320c-3e91-5241-fad3-248269eed104&limit=2&order=asc", "schedules": [ { "url": "http://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed109", "schedule": { }, "push": { } }, { "url": "http://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed10A", "schedule": { }, "push": { } } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ScheduleListingRequest request = ScheduleListingRequest.newRequest(); Response response = client.execute(request); List schedules = response.getBody().get().getSchedules(); ``` ```python from urbanairship import BasicAuthClient, ScheduledList client = BasicAuthClient( key='', secret='' ) for schedule in ScheduledList(client): print( schedule.name, schedule.url, schedule.push_ids, schedule.schedule, schedule.push ) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') scheduled_push_list = UA::ScheduledPushList.new(client: airship) scheduled_push_list.each do |schedule| puts(schedule) end ``` --- ## Pause a schedule {#pauseschedule} Pause a recurring scheduled message, preventing Airship from sending messages on a recurring scheduled message interval. Use the `/resume` endpoint to resume a schedule. The pause operation cannot be completed for recurring schedules that have schedule end times in the past. [Jump to examples ↓](#pauseschedule-examples) ### `POST /api/schedules/{schedule_id}/pause` {{< note >}} Paused schedules bear a `"paused": true` boolean. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): sch **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `schedule_id` | `string` | Required | The ID of the schedule you want to pause. | **Request body** A pause request is empty. **Content-Type:** `application/json` Type: `object` **Responses** **`204`** An API request was successful, but there is no response body to return. **`400`** Returned if the schedule end time for a recurring schedule is in the past. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`500`** Occurs if a schedule fails to pause. The error includes a list of `failed_triggers`, detailing the schedule triggers that caused this operation to fail. Response body: **Content-Type:** `application/json` - **`error`** `string` A description of the error. - **`error_code`** `integer` An error code representing the HTTP status and a more specific Airship error, if known. Default: `500` Example: `500` - **`failed_triggers`** `array[object]` - **`ok`** `boolean` If false, an error occurred. **Examples** *Example* ```http POST /api/schedules/5cde3564-ead8-9743-63af-821e12337812/pause HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```python from urbanairship import BasicAuthClient, ScheduledPush client = BasicAuthClient( key='', secret='' ) sched = ScheduledPush(client) sched.url = "http://go.urbanairship/api/schedules/5cde3564-ead8-9743-63af-821e12337812" sched.pause() ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ScheduleStatusRequest pauseRequest = ScheduleStatusRequest.pauseScheduleRequest("68b2d71f-1c10-4592-bd96-2725aee0ae57"); Response pauseResponse = client.execute(pauseRequest); ``` --- ## Resume a schedule {#resumeschedule} Resume a recurring schedule that you previously paused, beginning with the next scheduled interval. The resume operation cannot be completed for recurring schedules that have schedule end times in the past. [Jump to examples ↓](#resumeschedule-examples) ### `POST /api/schedules/{schedule_id}/resume` {{< note >}} Paused schedules bear a `"paused": true` boolean. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): sch **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `schedule_id` | `string` | Required | The ID of the schedule you want to resume. | **Request body** A resume request is empty. **Content-Type:** `application/json` Type: `object` **Responses** **`204`** An API request was successful, but there is no response body to return. **`400`** Returned if the schedule end time is in the past. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`500`** Occurs if a schedule fails to resume. The error includes a list of `failed_triggers`, detailing the specific schedule IDs that caused the operation to fail. Response body: **Content-Type:** `application/json` - **`error`** `string` A description of the error. - **`error_code`** `integer` An error code representing the HTTP status and a more specific Airship error, if known. Default: `500` Example: `500` - **`failed_triggers`** `array[object]` - **`ok`** `boolean` If false, an error occurred. **Examples** *Example* ```http POST /api/schedules/5cde3564-ead8-9743-63af-821e12337812/resume HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```python from urbanairship import BasicAuthClient, ScheduledPush client = BasicAuthClient( key='', secret='' ) sched = ScheduledPush(client) sched.url = "http://go.urbanairship/api/schedules/5cde3564-ead8-9743-63af-821e12337812" sched.resume() ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ScheduleStatusRequest resumeRequest = ScheduleStatusRequest.resumeScheduleRequest("68b2d71f-1c10-4592-bd96-2725aee0ae57"); Response resumeResponse = client.execute(resumeRequest); ``` --- ## Schedule a notification {#schedulenotification} Scheduled notifications are created by POSTing to the schedule URI. The body of the request must be one of a single [schedule object](/docs/developer/rest-api/ua/schemas/schedules/#scheduleobject) or an array of one or more schedule objects. [Jump to examples ↓](#schedulenotification-examples) ### `POST /api/schedules` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): psh **Request body** A single schedule object or an array of schedule objects. For Local Time Delivery, include no more than 100 Schedule Objects in your batch request. **Content-Type:** `application/json` **One of:** - `array` - [Schedule object]({{< ref "/developer/rest-api/ua/schemas/schedules/" >}}#scheduleobject) A schedule object consists of a schedule, i.e., a future delivery time, an optional name, and a push object. **Responses** **`201`** The response body will contain an array of response objects with the created resource URIs. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string which identifies a single API call, and can be used to group multiple entities or side effects as related, in reporting and troubleshooting logs. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`schedule_ids`** `array[string]` An array of schedule IDs, each string uniquely identifying a schedule. Min items: 1, Max items: 100 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`schedule_urls`** `array[string]` An array of schedule URLs. Min items: 0, Max items: 100 - **`schedules`** `array` <[Schedule object]({{< ref "/developer/rest-api/ua/schemas/schedules/" >}}#scheduleobject)> An array of schedule objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/schedules HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json [ { "name": "Morning People", "schedule": { "scheduled_time": "2020-06-03T09:15:00" }, "push": { "audience": { "tag": "earlyBirds" }, "notification": { "alert": "Good Day Sunshine" }, "device_types": [ "ios", "android" ] } }, { "name": "Everybody Else", "schedule": { "best_time": { "send_date": "2020-06-03" } }, "push": { "audience": { "tag": "normalPeople" }, "notification": { "alert": "Stay Up Late" }, "device_types": [ "ios", "android" ] } } ] ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SchedulePayload schedulePayload = SchedulePayload.newBuilder() .setName("Morning People") .setSchedule(Schedule.newBuilder() .setScheduledTimestamp(DateTime.parse("2020-06-03T09:15:00Z")) .build()) .setPushPayload(PushPayload.newBuilder() .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID)) .setNotification(Notifications.alert("Good Day Sunshine")) .setAudience(Selectors.tag("earlyBirds")) .build()) .build(); ScheduleRequest scheduleRequest = ScheduleRequest.newRequest(schedulePayload); Response response = client.execute(scheduleRequest); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, ScheduledPush, Push, tag, notification, scheduled_time ) client = BasicAuthClient( key='', secret='' ) # Create the push payload push = Push(client) push.audience = tag('earlyBirds') push.notification = notification(alert='Good Day Sunshine') push.device_types = ['ios', 'android'] # Create the schedule sched = ScheduledPush(client) sched.name = 'Morning People' sched.schedule = scheduled_time(datetime(2020, 6, 3, 9, 15, 0)) sched.push = push # Send the scheduled push response = sched.send() print('Created schedule. URL:', response.schedule_url) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') push = airship.create_push push.audience = UA.tag('earlyBirds') push.notification = UA.notification(alert: 'Morning People') push.device_types = UA.device_types(['ios','android']) schedule = airship.create_scheduled_push schedule.push = push schedule.name = "Morning People" schedule.schedule = UA.scheduled_time(Time.now.utc + 60) response = schedule.send_push print ("Created schedule. url: " + response.schedule_url) ``` *Example schedule with localizations* ```http POST /api/schedules HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json [ { "name": "Greetings", "schedule": { "best_time": { "send_date": "2020-11-15" } }, "push": { "device_types": [ "ios", "android" ], "audience": { "tag": "needs_a_greeting", "group": "new_customer" }, "notification": { "alert": "Hi!" }, "localizations": [ { "language": "de", "country": "AT", "notification": { "alert": "Grüss Gott" } }, { "language": "de", "country": "DE", "notification": { "alert": "Guten Tag" } } ] } } ] ``` ```http HTTP/1.1 201 Created Data-Attribute: schedule_urls Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "efb18e92-9a60-6689-45c2-82fedab36399", "schedule_urls": [ "https://go.urbanairship.com/api/schedules/eac2ace6-349a-41a2-b874-5496d7bf0100", "https://go.urbanairship.com/api/schedules/6c7c9bf5-cb2b-47cb-b27f-f85981391c4e" ], "schedule_ids": [ "eac2ace6-349a-41a2-b874-5496d7bf0100", "6c7c9bf5-cb2b-47cb-b27f-f85981391c4e" ], "schedules": [ { "url": "https://go.urbanairship.com/api/schedules/eac2ace6-349a-41a2-b874-5496d7bf0100", "schedule": { "scheduled_time": "2020-06-03T09:15:00" }, "name": "Morning People", "push": { "audience": { "tag": "earlyBirds" }, "notification": { "alert": "Good Day Sunshine" }, "device_types": [ "ios", "android" ] }, "push_ids": [ "83046227-9b06-4114-9f23-0df349792bbd" ] } { "url": "https://go.urbanairship.com/api/schedules/6c7c9bf5-cb2b-47cb-b27f-f85981391c4e", "schedule": { "best_time": { "send_date": "2020-06-03" } }, "name": "Everybody Else", "push": { "audience": { "tag": "normalPeople" }, "notification": { "alert": "Stay Up Late" }, "device_types": [ "ios", "android" ] }, "push_ids": [ "8438e81-bb31-82a9-5feb-e7fd5b21ca7e" ] } ] } ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, ScheduledPush, Push, tag_group, notification, best_time, localization ) client = BasicAuthClient( key='', secret='' ) # Create the push payload push = Push(client) push.audience = tag_group('new_customer', 'needs_a_greeting') push.notification = notification(alert='Hi!') push.device_types = ['ios', 'android'] push.localizations = [ localization( country='AT', language='de', notification=notification(alert='Grüss Gott') ), localization( country='DE', language='de', notification=notification(alert='Guten Tag') ) ] # Create the schedule sched = ScheduledPush(client) sched.name = 'Greetings' sched.schedule = best_time(send_date=datetime(2020, 11, 15)) sched.push = push # Send the scheduled push response = sched.send() print('Created schedule. URL:', response.schedule_url) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); Localization one = Localization.newBuilder() .setCountry("AT") .setLanguage("de") .setNotification(Notifications.alert("Grüss Gott")) .build(); Localization two = Localization.newBuilder() .setCountry("DE") .setLanguage("de") .setNotification(Notifications.alert("Guten Tag")) .build(); SchedulePayload schedulePayload = SchedulePayload.newBuilder() .setName("Greetings") .setSchedule(Schedule.newBuilder() .setBestTime(BestTime.newBuilder() .setSendDate(DateTime.parse("2020-11-15T00:00:00Z")) .build()) .build()) .setPushPayload(PushPayload.newBuilder() .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID)) .setNotification(Notifications.alert("Hi!")) .setAudience(Selectors.tagWithGroup("needs_a_greeting", "new_customer")) .addLocalization(one) .addLocalization(two) .build()) .build(); ScheduleRequest scheduleRequest = ScheduleRequest.newRequest(schedulePayload); Response response = client.execute(scheduleRequest); ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') push = airship.create_push push.audience = UA.tag('needs_a_greeting', group:'new_customer') push.notification = UA.notification(alert: 'Hi!') push.device_types = UA.device_types(['ios', 'android']) push.localizations = { "language": "de", "country": "AT", "notification": { "alert": "Grüss Gott" } } schedule = airship.create_scheduled_push schedule.push = push schedule.name = "Greetings" schedule.schedule = UA.scheduled_time(Time.now.utc + 60) response = schedule.send_push print ("Created schedule. url: " + response.schedule_url) ``` --- ## Update schedule {#updateschedule} Update the state of a single schedule resource. The body must contain a single schedule object. A PUT cannot be used to create a new schedule; it can only be used to update an existing one. A push to local time schedule cannot be updated once it has begun sending pushes to a time zone. [Jump to examples ↓](#updateschedule-examples) ### `PUT /api/schedules/{schedule_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): sch **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `schedule_id` | `string` | Required | The ID of a schedule. | **Request body** A single schedule object. **Content-Type:** `application/json` [Schedule object]({{< ref "/developer/rest-api/ua/schemas/schedules/" >}}#scheduleobject) **Responses** **`200`** Returned if the scheduled push has been successfully updated. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` Success. - **`operation_id`** `string` A unique string which identifies a single API call, and can be used to group multiple entities or side effects as related, in reporting and troubleshooting logs. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`schedule_urls`** `array[string]` An array of schedule URLs. Min items: 0, Max items: 100 Example: `https://go.urbanairship/api/schedules/2d69320c-3c91-5241-fac4-248269eed109` - **`schedules`** `array` <[Schedule object]({{< ref "/developer/rest-api/ua/schemas/schedules/" >}}#scheduleobject)> An array of schedule objects. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`409`** Returned if the local time scheduled push is in progress. **`413`** Returned when the request is too large to be processed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http PUT /api/schedules/5cde3564-ead8-9743-63af-821e12337812 HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name": "I would like to subscribe to your newsletter", "schedule": { "scheduled_time": "2020-04-01T18:45:30" }, "push": { "audience": { "tag": [ "intriguing", "ideas", "thought_leadership" ] }, "notification": { "alert": "Check your inbox!" }, "device_types": [ "ios", "android" ] } } ``` ```http HTTP/1.1 200 OK Content-Length: 123 Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "7c56d013-5599-d66d-6086-6205115d85e2", "schedule_urls": [ "https://go.urbanairship.com/api/schedules/0af1dead-e769-4b78-879a-7c4bb52d7c9e" ], "schedules": [ { "url": "https://go.urbanairship.com/api/schedules/0af1dead-e769-4b78-879a-7c4bb52d7c9e", "schedule": { "scheduled_time": "2020-04-01T18:45:30" }, "name": "I would like to subscribe to your newsletter", "push": { "audience": {"tag": ["intriguing", "ideas", "thought_leadership"] }, "notification": {"alert": "Check your inbox!"}, "device_types": [ "ios", "android" ] }, "push_ids": [ "48fb8e8a-ee51-4e2a-9a47-9fab9b13d846" ] } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SchedulePayload schedulePayload = SchedulePayload.newBuilder() .setName("I would like to subscribe to your newsletter") .setSchedule(Schedule.newBuilder() .setScheduledTimestamp(DateTime.parse("2020-04-01T18:45:00Z")) .build()) .setPushPayload(PushPayload.newBuilder() .setDeviceTypes(DeviceTypeData.of(DeviceType.IOS, DeviceType.ANDROID)) .setNotification(Notifications.alert("Check your inbox!")) .setAudience(Selectors.tag("intriguing")) .build()) .build(); ScheduleRequest scheduleRequest = ScheduleRequest.newUpdateRequest(schedulePayload, "5cde3564-ead8-9743-63af-821e12337812"); Response response = client.execute(scheduleRequest); ``` ```python from datetime import datetime from urbanairship import ( BasicAuthClient, ScheduledPush, Push, tag, notification, scheduled_time ) client = BasicAuthClient( key='', secret='' ) schedule = ua.ScheduledPush.from_url(client, 'https://go.urbanairship.com/api/schedules/5cde3564-ead8-9743-63af-821e12337812') # change scheduled time to tomorrow schedule.schedule = scheduled_time(datetime.datetime.utcnow() + datetime.timedelta(days=1)) resp = schedule.update() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') schedule = airship.create_scheduled_push schedule = UA::ScheduledPush.from_url(client: airship, url: 'https://go.urbanairship.com/api/schedules/5cde3564-ead8-9743-63af-821e12337812') # change scheduled time to tomorrow schedule.schedule = UA.scheduled_time(Time.now.utc + (60 * 60 * 24)) schedule.update ``` --- # Segments > Segments are portions of your audience that have arbitrary metadata (e.g., tags, location data, etc.) attached. You can create, delete, update, or request information on a Segment via the `/api/segments/` endpoint. Pushing to a Segment is done through the `/api/push/` endpoint. See the [Audience selection](/developer/rest-api/ua/schemas/audience-selection/) section for more information. ## Create Segment {#createsegment} Create a new Segment. [Jump to examples ↓](#createsegment-examples) ### `POST /api/segments` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Request body** A single Segment object. **Content-Type:** `application/json` - **`criteria`** `object` **REQUIRED** Defines the set of devices to send notifications to. `criteria` is a JSON expression containing the same information as the audience selector, including [Event Segmentation](/docs/developer/rest-api/ua/schemas/event-segmentation/). See [Audience selection](/docs/developer/rest-api/ua/schemas/audience-selection/) for more information. **One of:** - [Compound selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#compoundselector) Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. - [Atomic selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#atomicselector) Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. - **`display_name`** `string` **REQUIRED** Human readable name for this Segment. This will be used in the dashboard. Example: `News but not sports` **Responses** **`201`** The Segment was created. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The newly created Segment. | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If true, the operation completed successfully and returns expected results. - **`operation_id`** `string` A unique string identifying an API call, and can be used to identify operations in reporting and troubleshooting logs. Format: `uuid` Example: `ef625038-70a3-41f1-826f-57bc11dd625a` - **`segment_id`** `string` The ID of the newly created Segment. Format: `uuid` Example: `1d154121-951f-45b9-896d-e70718b5865b` **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/segments HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "display_name": "News but not sports", "criteria": { "and": [ {"tag": "news"}, {"not": {"tag": "sports"} } ] } } ``` ```http HTTP/1.1 201 Created Location: https://go.urbanairship.com/api/segments/f35da41d-59c1-4106-a192-9594bd480cb6 Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "segment_id": "f35da41d-59c1-4106-a192-9594bd480cb6", "operation_id": "1d154121-951f-45b9-896d-e70718b5865b" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); // Define the segment criteria Selector compound = Selectors.and(Selectors.tag("news"), Selectors.not(Selectors.tag("sports"))); SegmentRequest request = SegmentRequest.newRequest(); request.setCriteria(compound); request.setDisplayName("News but not sports"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Segment, tag, not_, and_ ) client = BasicAuthClient( key='', secret='' ) # Create a new segment segment = Segment() segment.display_name = "News but not sports" segment.criteria = and_( tag('news'), not_(tag('sports')) ) # Create the segment response = segment.create(client) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') segment = UA::Segment.new(client: airship) segment.display_name = 'Display Name' segment.criteria = { 'tag' => 'existing_tag' } segment.create ``` --- ## Delete Segment {#deletesegment} Remove the Segment. [Jump to examples ↓](#deletesegment-examples) ### `DELETE /api/segments/{segment_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `segment_id` | `string` | Required | The Segment you want to retrieve. | **Responses** **`204`** An API request was successful, but there is no response body to return. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http DELETE /api/segments/00c0d899-a595-4c66-9071-bc59374bbe6b HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 204 No Content ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SegmentDeleteRequest request = SegmentDeleteRequest.newRequest("00c0d899-a595-4c66-9071-bc59374bbe6b"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Segment ) client = BasicAuthClient( key='', secret='' ) # Delete a segment segment = Segment() segment.from_id(client, "00c0d899-a595-4c66-9071-bc59374bbe6b") response = segment.delete(client) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') segment = UA::Segment.new(client: airship) segment.from_id(id: '00c0d899-a595-4c66-9071-bc59374bbe6b') segment.delete ``` --- ## Segment listing {#getsegments} List all segments for the application. [Jump to examples ↓](#getsegments-examples) ### `GET /api/segments` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Query parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `limit` | `integer` | | Set the limit to 200 or fewer Segment objects per request. Max: 200 | **Responses** **`200`** Returned on success a JSON object containing segments. Response headers: | Name | Type | Description | |------|------|-------------| | `Link` | `string` | A link to the next page of results. If present, follow this URL to the next page of segments. Also available in the `next_page` value in the response body. | Response body: **Content-Type:** `application/json` - **`next_page`** `string` An optional relative URL which can be used to retrieve the next page of results. If no more results are available, next_page will be absent. - **`segments`** `array[object]` **REQUIRED** An array of segments for the application. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/segments/ HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Link: ;rel=next Content-Type: application/vnd.urbanairship+json; version=3 { "next_page": "https://go.urbanairship.com/api/segments?limit=1&sort=id&order=asc&start=3832cf72-cb44-4132-a11f-eafb41b82f64", "segments": [ { "creation_date": 1346248822221, "display_name": "A segment", "id": "00c0d899-a595-4c66-9071-bc59374bbe6b", "modification_date": 1346248822221 } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SegmentListingRequest request = SegmentListingRequest.newRequest(); Response response = client.execute(request); // Get the first segment in the list SegmentListingView segment = response.getBody().get().getSegmentListingViews().get(0); // Get the segment display name String displayName = segment.getDisplayName(); // Get the segment ID String id = segment.getSegmentId(); ``` ```python from urbanairship import ( BasicAuthClient, SegmentList ) client = BasicAuthClient( key='', secret='' ) # List all segments segment_list = SegmentList(client) for segment in segment_list: print(segment.display_name) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') segment_list = UA::SegmentList.new(client: airship) segment_list.each do |segment| puts(segment['display_name']) end ``` --- ## Segment lookup {#getsegment} Lookup a Segment. [Jump to examples ↓](#getsegment-examples) ### `GET /api/segments/{segment_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `segment_id` | `string` | Required | The Segment you want to retrieve. | **Responses** **`200`** Returns OK for success. Response body: **Content-Type:** `application/json` - **`criteria`** `object` **REQUIRED** Defines the set of devices to send notifications to. `criteria` is a JSON expression containing the same information as the audience selector, including [Event Segmentation](/docs/developer/rest-api/ua/schemas/event-segmentation/). See [Audience selection](/docs/developer/rest-api/ua/schemas/audience-selection/) for more information. **One of:** - [Compound selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#compoundselector) Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. - [Atomic selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#atomicselector) Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. - **`display_name`** `string` **REQUIRED** Human readable name for this Segment. This will be used in the dashboard. Example: `News but not sports` **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/segments/00c0d899-a595-4c66-9071-bc59374bbe6b HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "criteria": { "and": [ { "tag": "ipad" }, { "not": { "tag": "foo" } } ] }, "display_name": "A segment" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SegmentLookupRequest request = SegmentLookupRequest.newRequest("00c0d899-a595-4c66-9071-bc59374bbe6b"); Response response = client.execute(request); // Get the segment criteria Selector criteria = response.getBody().get().getCriteria(); // Get the segment display name String displayName = response.getBody().get().getDisplayName(); ``` ```python from urbanairship import ( BasicAuthClient, Segment ) client = BasicAuthClient( key='', secret='' ) # Look up a segment by ID segment = Segment() response = segment.from_id(client, "00c0d899-a595-4c66-9071-bc59374bbe6b") ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') segment = UA::Segment.new(client: airship) details = segment.from_id(id: '00c0d899-a595-4c66-9071-bc59374bbe6b') ``` --- ## Update Segment {#updatesegment} Change the definition of the Segment. [Jump to examples ↓](#updatesegment-examples) ### `PUT /api/segments/{segment_id}` {{< note >}} Segmentation data is evaluated at send time. If you schedule a message that targets a Segment and then edit that Segment, the scheduled message automatically uses the updated Segment criteria. "Scheduled" includes recurring messages. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `segment_id` | `string` | Required | The Segment you want to retrieve. | **Request body** A single Segment object. **Content-Type:** `application/json` - **`criteria`** `object` **REQUIRED** Defines the set of devices to send notifications to. `criteria` is a JSON expression containing the same information as the audience selector, including [Event Segmentation](/docs/developer/rest-api/ua/schemas/event-segmentation/). See [Audience selection](/docs/developer/rest-api/ua/schemas/audience-selection/) for more information. **One of:** - [Compound selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#compoundselector) Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. - [Atomic selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#atomicselector) Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. - **`display_name`** `string` **REQUIRED** Human readable name for this Segment. This will be used in the dashboard. Example: `News but not sports` **Responses** **`200`** Returned if the Segment has been successfully updated. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http PUT /api/segments/00c0d899-a595-4c66-9071-bc59374bbe6b HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "display_name": "Entertainment but not sports", "criteria": { "and": [ {"tag": "entertainment"}, {"not": {"tag": "sports"} } ] } } ``` ```http HTTP/1.1 200 OK Content-Length: 65 Content-Type: application/vnd.urbanairship+json;version=3 { "ok": true, "operation_id": "1f93ca85-b8fd-4833-8d1a-6e2b7f4ceea9" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); // Define the segment criteria Selector compound = Selectors.and(Selectors.tag("entertainment"), Selectors.not(Selectors.tag("sports"))); SegmentRequest request = SegmentRequest.newUpdateRequest("00c0d899-a595-4c66-9071-bc59374bbe6b"); request.setCriteria(compound); request.setDisplayName("Entertainment but not sports"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Segment, tag, not_, and_ ) client = BasicAuthClient( key='', secret='' ) # Update an existing segment segment = Segment() segment.from_id(client, "00c0d899-a595-4c66-9071-bc59374bbe6b") # Update segment properties segment.display_name = "Entertainment but not sports" segment.criteria = and_( tag('entertainment'), not_(tag('sports')) ) # Save the changes response = segment.update(client) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') segment = UA::Segment.new(client: airship) segment.from_id(id: '00c0d899-a595-4c66-9071-bc59374bbe6b') segment.display_name = 'New Display Name' segment.criteria = { 'tag' => 'new_tag' } segment.update ``` --- # SMS > Register and manage SMS channels. See [SMS Platform Information](/developer/api-integrations/sms/) to get started with SMS notifications. ## Custom SMS response {#createcustomsmsresponse} Respond to a mobile-originated message based on a keyword consumed by your custom-response webhook, using a mobile-originated ID. See [SMS Keyword Webhooks](/docs/developer/api-integrations/sms/inbound-message-handling/) for information about setting up a custom response webhook server. [Jump to examples ↓](#createcustomsmsresponse-examples) ### `POST /api/sms/custom-response` **Security:** - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Request headers:** | Name | Type | Required | Description | |------|------|----------|-------------| | `X-UA-Appkey` | `string` | Required | The application key for your project. | **Request body** **Content-Type:** `application/json` **One of:** - **`mobile_originated_id`** `string` **REQUIRED** The identifier that you received through your SMS webhook corresponding to the mobile-originated message that you're issuing a custom response to. The `mobile_originated_id` is valid for 10 minutes from the `received_timestamp` in the payload sent to your webhook server's `/inbound-sms` endpoint. Format: `uuid` - **`sms`** `object` **REQUIRED** **OBJECT PROPERTIES** - **`alert`** `string` **REQUIRED** Your custom SMS message. - **`shorten_links`** `boolean` If true, Airship will shorten HTTP/HTTPS links (space delimited) in the message text fields, producing unique, 25 character URLs for each member of your audience. Airship produces `short_link_click` events in the Real-Time Data Stream for each link that a user engages with. When this setting is enabled, you can add or remove tags from users who click your links by adding query strings to your URLs. You can serialize tag operations with `&`: * `?ua-tag-add=tag_group:tag&another_group:tag2` — adds a tag in `tag_group` to the `channel_id`. * `?ua-tag-remove=tag_group:tag&another_group:tag2` — removes a tag in `tag group` from the `channel_id`. * `?ua-list-add=subscription_list_id` — adds the user's channel to the `subscription list`. * `?ua-list-remove=subscription_list_id` — removes the user's channel from the `subscription list`. Default: `false` - **`mms`** `object` <[MMS platform overrides]({{< ref "/developer/rest-api/ua/schemas/platform-overrides/" >}}#mmsoverrideobject)> **REQUIRED** Provides the content for a push to MMS channels. If `sms` is in the `device_type` array, your request may include this object. It cannot be combined with an SMS Platform Override as a single push can only include either an SMS or MMS payload. - **`mobile_originated_id`** `string` **REQUIRED** The identifier that you received through your SMS webhook corresponding to the mobile-originated message that you're issuing a custom response to. The `mobile_originated_id` is valid for 10 minutes from the `received_timestamp` in the payload sent to your webhook server's `/inbound-sms` endpoint. Format: `uuid` **Responses** **`200`** The operation was successful. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If `true`, your request was successful. - **`operation_id`** `string` A unique identifier for an operation; you can use this identifier to find the operation for troubleshooting purposes. Format: `uuid` - **`push_id`** `string` A unique identifier for a push operation. Format: `uuid` **`404`** The mobile_originated_id could not be found. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`error`** `string` A plain-text explanation of the error. - **`ok`** `boolean` If false, your request was unsuccessful. - **`operation_id`** `string` A unique identifier for an operation; you can use this identifier to find the operation for troubleshooting purposes. Format: `uuid` **Examples** *SMS example* ```http POST /api/sms/custom-response HTTP/1.1 Authorization: Bearer X-UA-Appkey: Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "sms" : { "alert": "Your balance is $1234.56. Go to https://www.example.com/myaccount/my-balance?ua-tag-add=balance_prefs:sms to see more about your account.", "shorten_links": true }, "mobile_originated_id" : "28883743-4868-4083-ab5d-77ac4542531a" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setBearerToken("") .build(); CustomSmsResponseSmsPayload customSmsResponseChannelSms = CustomSmsResponseSmsPayload.newBuilder() .setAlert("Your balance is $1234.56. Go to https://www.example.com/myaccount/my-balance?ua-tag-add=balance_prefs:sms to see more about your account.") .setMobileOriginatedId("28883743-4868-4083-ab5d-77ac4542531a") .setShortenLinks(true) .build(); CustomSmsResponseRequest customSmsResponseRequest = CustomSmsResponseRequest.newRequest(customSmsResponseChannelSms); Response response = client.execute(customSmsResponseRequest); ``` ```python from urbanairship import ( BearerTokenClient, SmsCustomResponse, sms, mms ) client = BearerTokenClient( app_key='', token='' ) custom_response = SmsCustomResponse( client=client, mobile_originated_id="28883743-4868-4083-ab5d-77ac4542531a" ) custom_response.sms = sms( alert="Your balance is $1234.56. Go to https://www.example.com/myaccount/my-balance?ua-tag-add=balance_prefs:sms to see more about your account.", shorten_links=True ) response = custom_response.send() ``` *MMS example* ```http POST /api/sms/custom-response HTTP/1.1 Authorization: Bearer X-UA-Appkey: Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "mms" : { "fallback_text": "See fun cat pics at https://example.com/cat/pics/12345678", "slides": [ { "media": { "url": "https://example.com/cat/pics/12345678.gif", "content_type": "image/gif", "content_length": 23098 } } ], "shorten_links": true }, "mobile_originated_id" : "3e1e4fb3-2d3c-431e-96bf-9b235a12f84b" } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "operation_id": "f3d0993e-e3e1-4aae-b1c0-864a715bfaff", "push_id": "7502abe6-e6ea-4f2b-906f-ebbab612c69e" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setBearerToken("") .build(); MmsSlides mmsSlides = MmsSlides.newBuilder() .setText("Test") .setMediaUrl("https://example.com/cat/pics/12345678.gif") .setMediaContentType("image/gif") .setMediaContentLength(23098) .build(); CustomSmsResponseMmsPayload customSmsResponseMmsPayload = CustomSmsResponseMmsPayload.newBuilder() .setFallbackText("See fun cat pics at https://example.com/cat/pics/12345678") .setMobileOriginatedId("28883743-4868-4083-ab5d-77ac4542531a") .setSlides(mmsSlides) .build(); CustomSmsResponseRequest customSmsResponseRequest = customSmsResponseRequest.newRequest(customSmsResponseMmsPayload); Response response = client.execute(customSmsResponseRequest); ``` ```python from urbanairship import ( BearerTokenClient, SmsCustomResponse, mms ) client = BearerTokenClient( app_key='', token='' ) custom_response = SmsCustomResponse( client=client, mobile_originated_id="3e1e4fb3-2d3c-431e-96bf-9b235a12f84b" ) custom_response.mms = mms( fallback_text="See fun cat pics at https://example.com/cat/pics/12345678", slides=[{ "media": { "url": "https://example.com/cat/pics/12345678.gif", "content_type": "image/gif", "content_length": 23098 } }], shorten_links=True ) response = custom_response.send() ``` --- ## Manually trigger a keyword interaction {#triggersmskeywordinteraction} Trigger Mobile Originated (MO) keyword interactions on behalf of an MSISDN. [Jump to examples ↓](#triggersmskeywordinteraction-examples) ### `POST /api/sms/{msisdn}/keywords` **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `msisdn` | `string` | Required | The identifier for the SMS channel you want to trigger a mobile originated keyword from. | **Request headers:** | Name | Type | Required | Description | |------|------|----------|-------------| | `X-UA-Appkey` | `string` | Required | The application key for your project. | **Request body** **Content-Type:** `application/json` - **`keyword`** `string` **REQUIRED** The keyword you want to trigger an action for. Must be an alphanumeric string with no spaces. - **`sender_ids`** `array` <[Sender ID]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#sender_id)> **REQUIRED** The [sender IDs](/docs/developer/rest-api/ua/schemas/others/#sender_id) with keyword actions that you want to test. Airship returns a 400 if the `keyword` is not configured for one or more of the senders in the array. Min items: 1 - **`timestamp`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the MO keyword was sent. If absent, Airship uses the server-time of your request. Format: `date-time` **Responses** **`200`** The operation was successful. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If `true`, your request was successful. **`400`** The operation was not successful. If the request is formatted correctly, one or more `sender_ids` does not exist or the keyword is not configured for one or more of the `sender_ids`. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/sms/15035556789/keywords HTTP/1.1 User-Agent: Apache-HttpAsyncClient/4.0.1 (java 1.5) Content-Type: application/json Authorization: Basic Connection: close { "keyword" : "stop", "sender_ids" : [ "54321", "1234"] } ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); KeywordInteractionRequest request = KeywordInteractionRequest.newRequest("15035556789") .addKeyword("stop") .addSenderId("54321") .addSenderId("1234"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, KeywordInteraction ) from datetime import datetime client = BasicAuthClient( key='', secret='' ) interaction = KeywordInteraction( client=client, keyword="stop", sender_ids=["54321", "1234"], timestamp=datetime(2021, 10, 8, 12, 0, 0) ) response = interaction.post() ``` *Failure response (Keyword not configured for Sender ID)* ```http HTTP/1.1 400 Bad Request Content-Type: application/json { "ok" : false, "error" : "The following sender(s) are not configured for the 'stop' keyword: ['1234']", "error_code" : 400 } ``` --- ## Opt-out of SMS messages {#optoutsmschannel} This will mark an SMS channel as opted-out (inactive) and it will not receive alerts even when they are addressed in the future. To opt the user back in, call the registration function again with a valid `opted_in` value. [Jump to examples ↓](#optoutsmschannel-examples) ### `POST /api/channels/sms/opt-out` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`msisdn`** `string` **REQUIRED** The mobile phone number you want to opt-out of SMS messages. Must be numeric characters only, without leading zeros. 15 digits maximum. Max length: 15 - **`sender`** `string` **REQUIRED** A long or short code the app is configured to send from. For example, `12345`. **Responses** **`202`** The msisdn/channel is opted-out of SMS notifications. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If true, the operation completed successfully. **`400`** The request body is not valid. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`details`** `object` **OBJECT PROPERTIES** - **`error`** `string` Specific error message that explains why the request was unsuccessful. - **`error`** `string` Returned with 40x responses; explains why the request was unsuccessful. - **`error_code`** `integer` The 5-digit Airship error code, pointing to a more specific error than the HTTP status. - **`ok`** `boolean` If false, the request was unsuccessful. **Examples** *Example* ```http POST /api/channels/sms/opt-out HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "sender": "12345", "msisdn": "15035556789" } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SmsRegistrationRequest request = SmsRegistrationRequest .newOptOutRequest("12345", "15035556789"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Sms ) client = BasicAuthClient( key='', secret='' ) sms = Sms( client=client, sender='12345', msisdn='15035556789' ) response = sms.opt_out() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') sms_channel = UA::Sms.new(client: airship) sms_channel.msisdn = '15035556789' sms_channel.sender = '12345' sms_channel.opt_out ``` --- ## Register SMS channel {#registersmschannel} Create an SMS channel. If the channel has not opted in yet (the request did not contain `opted_in`), Airship creates the channel with `opt_in` set to `false` and the user receives a message prompting them to complete the opt-in flow; you can assign tags and organize `pending` channels before the user has finished the opt-in process, but you cannot send messages to channels until they opt in to your audience. SMS notifications require a `sender` - a number that recipients will receive SMS notifications from. [Contact Airship Sales](https://www.airship.com/contact-us/) or your Account Manager to provision your project for SMS notifications and complete the configuration. [Jump to examples ↓](#registersmschannel-examples) ### `POST /api/channels/sms` {{< note >}} Avoid repeated registration attempts. Repeated registrations of the same MSISDN and sender without an `opted_in` value will result in multiple opt-in instruction messages being sent to the MSISDN. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`attributes`** `object` An optional object containing the customer-provided attributes associated with the SMS channel. - **`locale_country`** `string` The ISO 3166 two-character country code. The value for this field becomes a tag in the `ua_locale_country` tag group. - **`locale_language`** `string` The ISO 639-1 two-character language code. The value for this field becomes a tag in the `ua_locale_language` tag group. - **`msisdn`** `string` **REQUIRED** The mobile phone number you want to register as an SMS channel (or send a request to opt-in). Must be numeric characters only, without leading zeros. Max length: 15 - **`opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) that represents the date and time when explicit permission was received from the user to receive messages. Format: `date-time` - **`sender`** `string` **REQUIRED** A long or short code the app is configured to send from. For example, `12345`. - **`tag_operations`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Optionally one or more tag group objects associated with the SMS channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`timezone`** `string` The IANA identifier for a time zone, e.g., `America/Los_Angeles`. The value in this field becomes a tag in the `timezone` tag group. **Responses** **`200`** A channel with this msisdn/sender combination already exists. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` **One of:** - **`attributes`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the attributes were set correctly. - **`channel_id`** `string` Unique Channel ID for the SMS channel. Format: `uuid` - **`ok`** `boolean` If true, Airship creates a channel value with `opt_in` set to `true`. - **`operation_id`** `string` A unique identifier for an operation; you can use this identifier to find the operation for troubleshooting purposes. Format: `uuid` - **`tags`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the tags were set correctly. - **`attributes`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the attributes were set correctly. - **`channel_id`** `string` **REQUIRED** Unique Channel ID for the SMS channel. This channel is created with `opt_in` set to `false`, as the user has not yet opted in to your audience. Format: `uuid` - **`ok`** `boolean` **REQUIRED** If true, Airship creates a channel with `opt_in` set to `false` and Airship sends a message prompting the user to opt in to your audience. - **`operation_id`** `string` **REQUIRED** A unique identifier for an operation; you can use this identifier to find the operation for troubleshooting purposes. Format: `uuid` - **`push_id`** `string` **REQUIRED** Identifies the message prompting the user to opt in to your audience, sent as a result of a request without an `opted_in` value. Format: `uuid` - **`status`** `string` **REQUIRED** The channel has been created but has not yet opted-in. Possible values: `pending` - **`tags`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the tags were set correctly. **`201`** The channel was created. If the request did not contain an `opted_in` value, the channel is created with a `pending` status and the channel's `opt_in` value is set to `false`; you can assign assign tags and organize `pending` channels before the user has finished the opt-in process, but you cannot send messages to channels until they complete the opt-in flow. Response headers: | Name | Type | Description | |------|------|-------------| | `location` | `string` | URI of the channel, used for later registrations. | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` **One of:** - **`attributes`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the attributes were set correctly. - **`channel_id`** `string` Unique Channel ID for the SMS channel. Format: `uuid` - **`ok`** `boolean` If true, Airship creates a channel value with `opt_in` set to `true`. - **`operation_id`** `string` A unique identifier for an operation; you can use this identifier to find the operation for troubleshooting purposes. Format: `uuid` - **`tags`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the tags were set correctly. - **`attributes`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the attributes were set correctly. - **`channel_id`** `string` **REQUIRED** Unique Channel ID for the SMS channel. This channel is created with `opt_in` set to `false`, as the user has not yet opted in to your audience. Format: `uuid` - **`ok`** `boolean` **REQUIRED** If true, Airship creates a channel with `opt_in` set to `false` and Airship sends a message prompting the user to opt in to your audience. - **`operation_id`** `string` **REQUIRED** A unique identifier for an operation; you can use this identifier to find the operation for troubleshooting purposes. Format: `uuid` - **`push_id`** `string` **REQUIRED** Identifies the message prompting the user to opt in to your audience, sent as a result of a request without an `opted_in` value. Format: `uuid` - **`status`** `string` **REQUIRED** The channel has been created but has not yet opted-in. Possible values: `pending` - **`tags`** `object` **OBJECT PROPERTIES** - **`ok`** `boolean` If `true`, the tags were set correctly. **`400`** The channel could not be created. This error occurs when the project is not configured with a valid sender, the request was missing required fields, or the MSISDN does not meet the E.164 international standard. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`errors`** `string` Returned with 40x responses; explains reason for the unsuccessful request. Example: `Unable to retrieve details for sender 12345 with app_key ` - **`ok`** `boolean` If false, the request was unsuccessful. **Examples** *Example* ```http POST /api/channels/sms HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "msisdn" : "15035556789", "sender": "12345", "opted_in": "2020-02-13T11:58:59", "timezone": "America/Los_Angeles", "locale_country": "US", "locale_language": "en", "tag_operations": { "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } }, "attributes": { "my_fav_attribute1": "attribute1", "my_fav_attribute2": "attribute2" } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SmsRegistrationRequest request = SmsRegistrationRequest .newRegistrationRequest("12345", "15035556789", DateTime.parse("2020-02-13T11:58:59Z")); Response response = client.execute(request); ``` ```python from urbanairship import ( BearerTokenClient, Sms ) from datetime import datetime client = BearerTokenClient( app_key='', token='' ) sms_channel = Sms( client=client, sender="12345", msisdn="15035556789", opted_in=datetime.fromisoformat("2020-02-13T11:58:59"), locale_country="US", locale_language="en", timezone="America/Los_Angeles" ) response = sms_channel.register() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') sms_channel = UA::Sms.new(client: airship) sms_channel.msisdn = '15035556789' sms_channel.sender = '12345' sms_channel.opted_in = '2020-02-13T11:58:59' sms_channel.register ``` *Response (With 'opted_in')* ```http HTTP/1.1 201 Created Location: https://go.urbanairship.com/api/channels/7c5d7328-9bb4-4ff7-86b0-96a5f1da5868 Content-Type: application/json { "ok": true, "operation_id": "62077236-d032-11e9-af71-ab156113d166", "channel_id": "7c5d7328-9bb4-4ff7-86b0-96a5f1da5868", "attributes": {"ok": true}, "tags": {"ok": true} } ``` *Response (Without 'opted_in')* ```http HTTP/1.1 202 Accepted Content-Type: application/json Location: https://go.urbanairship.com/api/channels/79fbe330-d033-11e9-adfb-df10b89c5e04 { "ok": true, "operation_id": "62077236-d032-11e9-af71-ab156113d166", "push_id": "26350f60-d033-11e9-80e3-33def0e528d1", "channel_id": "79fbe330-d033-11e9-adfb-df10b89c5e04", "status": "pending", "attributes": {"ok": true}, "tags": {"ok": true} } ``` *Response (Project not configured with sender)* ```http HTTP/1.1 400 Bad Request Content-Type: application/json { "ok": false, "errors": "Unable to retrieve details for sender 12345 with app_key " } ``` --- ## SMS channel lookup {#getsmschannel} Lookup an SMS channel by `msisdn` and `sender`. [Jump to examples ↓](#getsmschannel-examples) ### `GET /api/channels/sms/{msisdn}/{sender}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `msisdn` | `integer` | Required | The mobile phone number you want to lookup a channel for. 15 digits maximum; may not contain leading zeroes. | | `sender` | `integer` | Required | A long or short code the app is configured to send from. | **Responses** **`200`** Returns an SMS channel object. An SMS channel object includes tag groups for `ua_channel_type`, `ua_sender_id`, and `ua_opt_in`. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`channel`** `object` <[Channel listing object]({{< ref "/developer/rest-api/ua/schemas/channels/" >}}#channellistingobject)> Describes a channel listing object. - **`ok`** `boolean` Success. **`404`** A `channel_id` does not exist for the `msisdn` and `sender`. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`error`** `string` Returned with 40x responses; explains why the request was unsuccessful. - **`error_code`** `integer` The 5-digit Airship error code, pointing to a more specific error than the HTTP status. - **`ok`** `boolean` If false, the request was unsuccessful. **Examples** *Example* ```http GET /api/channels/sms/15035556789/12345 HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: channel Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "channel": { "channel_id": "84e36d69-873b-4ffe-81cd-e74c9f002057", "device_type": "sms", "installed": true, "push_address": null, "named_user_id": null, "alias": null, "tags": [], "tag_groups": { "ua_channel_type": [ "sms" ], "ua_sender_id": [ "12345" ], "ua_opt_in": [ "true" ] }, "created": "2020-04-27T22:06:21", "opt_in": true, "opt_in_date": "2022-07-07T03:23:13", "msisdn": "150355551234", "last_registration": "2020-05-14T19:51:38" } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ChannelRequest channelRequest = ChannelRequest.newSmsLookupRequest("15035556789","12345"); Response response = client.execute(channelRequest); ``` ```python from urbanairship import ( BasicAuthClient, Sms ) client = BasicAuthClient( key='', secret='' ) sms = Sms( client=client, sender='12345', msisdn='15035556789' ) channel_info = sms.lookup() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') sms_channel = UA::Sms.new(client: airship) sms_channel.msisdn = '15035556789' sms_channel.sender = '12345' sms_channel.lookup ``` *Example opt_out_date* ```http HTTP/1.1 200 OK Data-Attribute: channel Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "channel": { "channel_id": "84e36d69-873b-4ffe-81cd-e74c9f002057", "device_type": "sms", "installed": true, "push_address": null, "named_user_id": null, "alias": null, "tags": [], "tag_groups": { "ua_channel_type": [ "sms" ], "ua_sender_id": [ "12345" ], "ua_opt_in": [ "true" ] }, "created": "2020-04-27T22:06:21", "opt_in": false, "opt_in_date": "2022-07-07T03:23:13", "opt_out_date": "2022-07-08T03:23:13", "msisdn": "150355551234", "last_registration": "2020-05-14T19:51:38" } } ``` --- ## SMS tags {#modifysmschanneltags} Add, remove, or set tags for a single SMS channel. [Jump to examples ↓](#modifysmschanneltags-examples) ### `POST /api/channels/sms/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per channel. Adding more than 1,000 tags per channel can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per channel, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** A single request body can contain an `add` and/or `remove` field or a single `set` field. One or more of the `add`, `remove`, or `set` keys must be present in the request. **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Adds the specified tags to the channel. Tags that are already present are not modified/removed as a result of this operation. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** Specifies the MSISDN and sender you want to perform tag operations against. **OBJECT PROPERTIES** - **`msisdn`** `string` The mobile phone number corresponding to the SMS channel. Must be numeric characters only, without leading zeros. 15 digits maximum. Max length: 15 - **`sender`** `string` A long or short code the app is configured to send from. For example, `12345`. - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Removes the specified tags from the channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Assigns a list of tags exactly. Any previously set tags that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** Returns OK for success. If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 will be returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/sms/tags HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "sender": "12345", "msisdn": "15035556789" }, "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } } ``` --- ## Uninstall SMS channel {#uninstallsmschannel} **Removes phone numbers and accompanying data from Airship. Use with caution.** Uninstalling an SMS channel will prevent you from retrieving opt-in and opt-out history for the corresponding msisdn. If the uninstalled msisdn opts-in again, it will generate a new channel_id. The new channel_id cannot be reassociated with any opt-in information, tags, Named Users, Performance Analytics reports, or other information from the uninstalled SMS channel. [Jump to examples ↓](#uninstallsmschannel-examples) ### `POST /api/channels/sms/uninstall` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`msisdn`** `string` **REQUIRED** The mobile phone number you want to remove from the Airship system. Must be numeric characters only, without leading zeros. 15 digits maximum. Max length: 15 - **`sender`** `string` **REQUIRED** A long or short code the app is configured to send from. For example, `12345`. **Responses** **`202`** The SMS channel and all information associated with the msisdn is uninstalled. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If true, the operation was successful. **`400`** The request body is not valid. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`details`** `object` **OBJECT PROPERTIES** - **`error`** `string` Specific error message that explains why the request was unsuccessful. - **`error`** `string` Returned with 40x responses; explains why the request was unsuccessful. - **`error_code`** `integer` The 5-digit Airship error code, pointing to a more specific error than the HTTP status. - **`ok`** `boolean` If false, the request was unsuccessful. **Examples** *Example* ```http POST /api/channels/sms/uninstall HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "sender": "12345", "msisdn": "15035556789" } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SmsRegistrationRequest request = SmsRegistrationRequest .newUninstallRequest("12345", "15035556789"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, Sms ) client = BasicAuthClient( key='', secret='' ) sms = Sms( client=client, sender='12345', msisdn='15035556789' ) response = sms.uninstall() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') sms_channel = UA::Sms.new(client: airship) sms_channel.msisdn = '15035556789' sms_channel.sender = '12345' sms_channel.uninstall ``` --- ## Update SMS channel {#updatesmschannel} Update an existing SMS channel to reflect opt-in date, time zone and/or locale changes. The `msisdn` and `sender` in the request must match the existing channel or the request will 404. [Jump to examples ↓](#updatesmschannel-examples) ### `PUT /api/channels/sms/{channel_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `channel_id` | `string` | Required | The identifier for the SMS channel you want to update. | **Request body** **Content-Type:** `application/json` - **`locale_country`** `string` The ISO 3166 two-character country code. The value for this field becomes a tag in the `ua_locale_country` tag group. - **`locale_language`** `string` The ISO 639-1 two-character language code. The value for this field becomes a tag in the `ua_locale_language` tag group. - **`msisdn`** `string` **REQUIRED** The phone number corresponding to the `channel_id` in the request. You cannot change this value for the existing channel. Max length: 15 - **`opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) that represents when explicit permission was received from the user to receive messages. Format: `date-time` - **`sender`** `string` **REQUIRED** The sender corresponding to the `channel_id` in the request. You cannot change this value for an existing channel. - **`timezone`** `string` The IANA identifier for a time zone, e.g., `America/Los_Angeles`. The value in this field becomes a tag in the `timezone` tag group. **Responses** **`200`** The SMS channel was updated successfully. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` True if the request was successful. - **`operation_id`** `string` A unique identifier for an operation; you can use this identifier to find the operation for troubleshooting purposes. Format: `uuid` **`400`** The request to update the channel failed. This error occurs when the MSISDN does not fall into the geographical region supported by the sender or the request is incorrect, e.g., missing or mismatching `msisdn` or `sender`, the `msisdn` is not a valid E.164 standard MSISDN, or invalid timezone/locale values are supplied. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`errors`** `string` Returned with 40x responses; explains reason for the unsuccessful request. Example: `Unable to retrieve details for sender 12345 with app_key ` - **`ok`** `boolean` If false, the request was unsuccessful. **`404`** Occurs when the `msisdn` and/or `sender` don't match any existing `channel_id`. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`errors`** `string` A plain-text explanation of the error. - **`ok`** `boolean` If false, your request was unsuccessful. **Examples** *Example* ```http PUT /api/channels/sms/{channel_id} HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "msisdn": "15035556789", "sender": "12345", "opted_in": "2020-02-13T11:58:59", "timezone": "America/Los_Angeles", "locale_country": "US", "locale_language": "en" } ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "ok": true, } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); UpdateSmsChannel updateSmsChannel = UpdateSmsChannel.newBuilder() .setMsisdn("13609048615") .setSender("17372004196") .setOptedIn(DateTime.parse("2021-10-11T02:03:03")) .setLocaleCountry("US") .setLocaleLanguage("en") .setTimeZone("America/Los_Angeles") .build(); UpdateSmsChannelRequest updateSmsChannelRequest = UpdateSmsChannelRequest.newRequest("308303cf-9c10-4d71-9bc2-d9f3a671ed0c", updateSmsChannel); Response response = client.execute(updateSmsChannelRequest); ``` ```python from urbanairship import ( BearerTokenClient, Sms ) from datetime import datetime client = BearerTokenClient( app_key='', token='' ) sms_channel = Sms( client=client, sender="12345", msisdn="15035556789", opted_in=datetime.fromisoformat("2021-02-13T11:58:59"), locale_country="US", locale_language="en", timezone="America/Los_Angeles" ) # Update properties sms_channel.locale_country = "FR" sms_channel.opted_in = datetime.fromisoformat("2020-02-13T11:58:59") response = sms_channel.update() ``` --- # Static Lists > With the Static List API endpoint, you can target and manage lists of devices that are defined in systems outside of Airship. Any list or grouping of devices for which the canonical source of data about the members is elsewhere is a good candidate for Static Lists, e.g., members of a customer loyalty program. In the dashboard, they are referred to as [Uploaded Lists](/guides/audience/segmentation/audience-lists/uploaded/). Airship automatically deletes a Static list and all its versions after 90 days of inactivity. Timestamps used to calculate the 90-day period are the creation date, when updating list contents or metadata, and when sending a message (pushing) to the list. The creation date is the initial day one of the 90-day period. Each instance of updating or sending to the list resets the timestamp to day one. After automatic deletion or deleting from the Airship dashboard, the list is removed from the upload history, is no longer visible in the Airship dashboard or through API calls, and is no longer available for audience segmentation. ## Create list {#createstaticlist} Create a static list. The body of the request will contain several of the list object parameters, but the actual list content will be provided by a second call to the [upload](/docs/developer/rest-api/ua/operations/static-lists/#updatestaticlist) endpoint. You can upload up to 100 lists per project. [Jump to examples ↓](#createstaticlist-examples) ### `POST /api/lists` {{< note >}} `Content-Encoding: gzip` is supported and recommended on this endpoint to reduce network traffic. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Request body** **Content-Type:** `application/json` - **`description`** `string` An optional description for the list. Min length: 1, Max length: 1000 - **`extra`** `object` An optional JSON map of up to 100 key-value (string-to-string) pairs associated with the list. Keys in this object have a 64-character maximum; values can be up to 1,024 characters. - **`name`** `string` **REQUIRED** The name of the list, consists of up to 64 URL-safe characters. The name is how the list is identified, so it should be unique and memorable. Note: Since the `name` portion of the URL may represent any Unicode string, it must be encoded properly as a URI path component. The `encodeURIComponent` function in JavaScript can be used. Min length: 1, Max length: 64 **Responses** **`201`** The list was created successfully. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The URI of the list, used for later updates. | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`409`** The request conflicts with another request. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/lists HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name" : "platinum_members", "description" : "loyalty program platinum members", "extra" : { "key" : "value", "another" : "etc." } } ``` ```http HTTP/1.1 201 Created Location: https://go.urbanairship.com/api/lists/platinum_members Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); StaticListRequest request = StaticListRequest.newRequest("platinum_members") .setDescription("loyalty program platinum members") .addExtra("key", "value"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, StaticList ) client = BasicAuthClient( key='', secret='' ) # Create a new static list static_list = StaticList( client=client, name='platinum_members' ) static_list.description = 'loyalty program platinum members' static_list.extra = {'key': 'value'} response = static_list.create() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') static_list = UA::StaticList.new(client: airship) static_list.name = 'platinum_members' static_list.create(description: 'loyalty program platinum members') ``` --- ## Delete a list {#deletestaticlist} Delete a static list. [Jump to examples ↓](#deletestaticlist-examples) ### `DELETE /api/lists/{list_name}` {{< warning >}} If you are attempting to update a current list by deleting it and then recreating it with new data, stop and go to the [upload endpoint](/docs/developer/rest-api/ua/operations/static-lists/#updatestaticlist). There is no need to delete a list before uploading a new CSV file. Moreover, once you delete a list, you will be unable to create a list with the same name as the deleted list. {{< /warning >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The name of the list. | **Responses** **`204`** An API request was successful, but there is no response body to return. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** You cannot delete or modify lists with a `ua_` prefixed `name`. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http DELETE /api/lists/platinum_members HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 204 No Content ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); StaticListDeleteRequest request = StaticListDeleteRequest.newRequest("platinum_members"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, StaticList ) client = BasicAuthClient( key='', secret='' ) # Delete a static list static_list = StaticList( client=client, name='platinum_members' ) response = static_list.delete() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') static_list = UA::StaticList.new(client: airship) static_list.name = 'platinum_members' static_list.delete ``` --- ## Download a list of channels {#getstaticlist} Allows you to download the contents of a static list (as opposed to a `GET` `/api/lists/{list_name}`, which will return metadata about the list). The CSV output from this endpoint will only include entries originally uploaded as `ios_channel`, `android_channel`, or `amazon_channel`. [Jump to examples ↓](#getstaticlist-examples) ### `GET /api/lists/{list_name}/csv` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The `name` of the list you want to retrieve or update. | **Responses** **`200`** Returns a CSV list of channels. Response body: **Content-Type:** `text/csv` Type: `string` **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/lists/foobar/csv HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+csv; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: text/csv ios_channel,6d56ab7e-2c78-4ba9-ab11-d9b664ca2b32 ios_channel,d5ebe607-a3e6-4601-b97e-83ec604223fe ios_channel,fa599af7-43e4-4862-a570-1470bf6f53ff android_channel,0e91d0f2-c65d-4b40-b968-b9f8e8b0c987 android_channel,c346a3ce-5754-4d02-8ee5-500ce470a0b7 android_channel,e9a01369-5f74-4167-b660-df84014a2e57 amazon_channel,0356d138-d1d9-4572-b321-e1b67f4cd658 amazon_channel,24dc9a76-45fe-4b17-8ed7-841f96b658ad amazon_channel,4d6b59f8-6d8c-4151-8b13-cd58d6ac8c6e ``` ```python from urbanairship import ( BasicAuthClient, StaticList ) client = BasicAuthClient( key='', secret='' ) # Download a static list response = StaticList.download( client=client, list_name='platinum_members' ) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); StaticListDownloadRequest request = StaticListDownloadRequest.newRequest("foobar"); Response response = client.execute(request); ``` --- ## Get single list metadata {#getstaticlistmetadata} Retrieve information about one static list, specified in the URL. When looking up lists, the returned information may actually be a combination of values from both the last uploaded list and the last successfully processed list. If you create a list successfully, and then you update it and the processing step fails, then the list `status` will read `failed`, but the `channel_count` and `last_modified` fields will contain information on the last successfully processed list. [Jump to examples ↓](#getstaticlistmetadata-examples) ### `GET /api/lists/{list_name}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The name of the list. | **Responses** **`200`** List metadata retrieved successfully. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`description`** `string` An optional description for the list. Min length: 1, Max length: 1000 - **`extra`** `object` An optional JSON map of up to 100 key-value (string-to-string) pairs associated with the list. Keys in this object have a 64-character maximum; values can be up to 1,024 characters. - **`name`** `string` The name of the list, consists of up to 64 URL-safe characters. The name is how the list is identified, so it should be unique and memorable. Min length: 1, Max length: 64 - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/lists/platinum_members/ HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: static_list Link: ; rel=next Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "name" : "platinum_members", "description" : "loyalty program platinum members", "extra" : { "key" : "value" }, "created" : "2020-04-08T20:41:06", "last_updated" : "2020-05-01T18:00:27", "channel_count" : 1000, "status" : "ready" } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); StaticListLookupRequest request = StaticListLookupRequest.newRequest("platinum_members"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, StaticList ) client = BasicAuthClient( key='', secret='' ) # Look up a static list static_list = StaticList( client=client, name='platinum_members' ) response = static_list.lookup() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') static_list = UA::StaticList.new(client: airship) static_list.name = 'platinum_members' static_list.lookup ``` --- ## Retrieve lists {#getstaticlistsmetadata} Retrieve information about all static lists. This call returns a list of metadata that will not contain the actual lists of users. [Jump to examples ↓](#getstaticlistsmetadata-examples) ### `GET /api/lists` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Responses** **`200`** Lists metadata retrieved successfully. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`lists`** `array` <[List response object]({{< ref "/developer/rest-api/ua/schemas/others/" >}}#listobject)> An array of list objects. - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/lists HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Attribute: lists Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "lists" : [ { "name" : "platinum_members", "description" : "loyalty program platinum members", "extra" : { "key" : "value" }, "created" : "2020-04-08T20:41:06", "last_modified" : "2020-05-01T18:00:27", "channel_count": 3145, "status": "ready" }, { "name": "gold_members", "description": "loyalty program gold member", "extra": { "key": "value" }, "created": "2020-04-08T20:41:06", "last_updated": "2020-05-01T18:00:27", "channel_count": 678, "status": "ready" } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); StaticListListingRequest request = StaticListListingRequest.newRequest(); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, StaticLists ) client = BasicAuthClient( key='', secret='' ) # List all static lists static_lists = StaticLists(client) for static_list in static_lists: print( static_list.name, static_list.description, static_list.extra, static_list.created, static_list.last_updated, static_list.channel_count, static_list.status ) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') static_lists = UA::StaticLists.new(client: airship) static_lists.each do |static_list| puts(static_list) end ``` --- ## Update list contents {#updatestaticlist} Replace the contents of an existing static list via CSV file upload. Uploads must be newline-delimited identifiers (text/CSV) with commas as the delimiter. The CSV format is two columns: `identifier_type` and `identifier`. The `identifier` is the associated identifier you wish to send to. The `identifier_type` must be one of: * `named_user` * `ios_channel` * `android_channel` * `amazon_channel` * `sms_channel` * `email_channel` * `open_channel` * `web_channel` The first entry in the uploaded CSV may be a header row, which will be ignored. If present, the header row must contain exactly two entries, and the first column must not be an `identifier_type` as specified above. [Jump to examples ↓](#updatestaticlist-examples) ### `PUT /api/lists/{list_name}/csv` {{< note >}} The maximum number of `identifier_type,identifier` pairs that may be uploaded to a list is 10 million. `Content-Encoding: gzip` is supported and recommended on this endpoint to reduce network traffic. {{< /note >}} {{< warning >}} If an attempt to upload a list times out due to a poor connection, you must re-upload the list from scratch. Because we want to ensure that the entirety of a given list is successfully uploaded, we do not support partial list uploads. {{< /warning >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The `name` of the list you want to retrieve or update. | **Request body** **Content-Type:** `text/csv` Type: `string` **Responses** **`202`** The request has been accepted for processing. Response body: **Content-Type:** `application/json` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** Bad Request. Parsing or validating the request failed. | Error code | Description | |---|---| | 40002 | CSV contains too many identifiers | | 40003 | CSV contains an entry with a column count other than 2 | | 40004 | CSV contains an invalid `identifier_type` | | 40005 | CSV contains a channel `identifier` that is not a valid UUID | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http PUT /api/lists/platinum_members/csv HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv named_user,customer-42 named_user,room-27 ios_channel,5i4c91s5-9tg2-k5zc-m592150z5634 web_channel,d132f5b7-abcf-4920-aeb3-9132ddac3d5a android_channel,52b2b587-0152-4134-a8a0-38ae6933c88a email_channel,ab1a81e3-5af3-4c04-a7ae-d676960e6684 open_channel,6bcf3e63-a38a-44d8-8b0d-2fb5941e74ab sms_channel,ab1a81e3-aaf3-ac04-a7ae-a676960e6684 ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); File dataDirectory = new File("src/data"); String filePath = dataDirectory.getAbsolutePath() + "/platinum.csv"; StaticListUploadRequest request = StaticListUploadRequest.newRequest("platinum_members", filePath); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, StaticList ) client = BasicAuthClient( key='', secret='' ) # Upload a CSV file to a static list static_list = StaticList( client=client, name='platinum_members' ) with open('list.csv', 'r') as csv_file: response = static_list.upload(csv_file) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') static_list = UA::StaticList.new(client: airship) static_list.name = 'platinum_members' File.open('csv_file', 'rb') do |csv| static_list.upload(csv_file: csv, gzip: false) end ``` *Example request with header row* ```http PUT /api/lists/foobar/csv HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv Identifier Type,Identifier alias,some-user-12345 alias,some-user-12346 ios_channel,5b1a81e3-5af3-4c04-a7ae-d676960e6684 named_user,SODFHsodfuJ9433 named_user,"contains,comma" named_user,"contains""double-quote" ``` --- ## Update list metadata {#updatestaticlistmetadata} Update the metadata (`description`, `extras`, etc.) of a static list. [Jump to examples ↓](#updatestaticlistmetadata-examples) ### `PUT /api/lists/{list_name}` {{< note >}} To update the list contents, use the [list upload](/docs/developer/rest-api/ua/operations/static-lists/#updatestaticlist) endpoint. The update endpoint is used to update a list's metadata rather than the actual list of device identifiers. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The name of the list. | **Request body** The body of the request will contain a list metadata object, though you can omit the `name` attribute. If present, it must match the name provided in the URL. You cannot change the name of a list; it is the primary identifier for the list. **Content-Type:** `application/json` - **`description`** `string` An optional description for the list. Min length: 1, Max length: 1000 - **`extra`** `object` An optional JSON map of up to 100 key-value (string-to-string) pairs associated with the list. Keys in this object have a 64-character maximum; values can be up to 1,024 characters. - **`name`** `string` **REQUIRED** The name of the list, consists of up to 64 URL-safe characters. The name is how the list is identified, so it should be unique and memorable. Note: Since the `name` portion of the URL may represent any Unicode string, it must be encoded properly as a URI path component. The `encodeURIComponent` function in JavaScript can be used. Min length: 1, Max length: 64 **Responses** **`200`** The list metadata was updated successfully. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** Bad Request. Parsing or validating the request failed. error_code 40001: Attempted list rename. List renaming is not allowed. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Forbidden. Authentication was correct, but the user does not have permission to access the requested API, e.g., the API may not be used to create or modify lists with a `ua_` prefixed name. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http PUT /api/lists/platinum_members HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name" : "platinum_members", "description" : "loyalty program platinum members", "extra" : { "key" : "value" } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); StaticListRequest request = StaticListRequest.newUpdateRequest("platinum_members") .setDescription("loyalty program platinum members") .addExtra("key", "value"); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, StaticList ) client = BasicAuthClient( key='', secret='' ) # Update an existing static list static_list = StaticList( client=client, name='platinum_members' ) static_list.description = 'loyalty program platinum members' static_list.extra = {'key': 'value'} response = static_list.update() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') static_list = UA::StaticList.new(client: airship) static_list.name = 'platinum_members' static_list.update(description: 'loyalty program platinum members') ``` --- # Subscription Lists > Create, manage, and add or remove channels from subscription lists. ## Named User subscription lists listing {#getnamedusersubscriptionlists} Provides the subscription lists that are associated with a given Named User. [Jump to examples ↓](#getnamedusersubscriptionlists-examples) ### `GET /api/subscription_lists/named_users/{named_user_id}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `named_user_id` | `string` | Required | The Named User being looked up. | **Responses** **`200`** Returns OK for success, with the Named User subscription list IDs. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` Success. - **`subscription_lists`** `array` <[Contact Subscription List object]({{< ref "/developer/rest-api/ua/schemas/subscription-lists/" >}}#contactsubscriptionlistobject)> **`304`** An If-Modified-Since request header exists and the result is unchanged. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/subscription_lists/named_users/4cbd1c1c-42e1-4606-bc93-9b707bcedcbc HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "subscription_lists": [ { "list_ids": ["example_listId-2", "example_listId-4"], "scope": "app" }, { "list_ids": ["example_listId-2"], "scope": "web" } ], } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserSubscriptionListsListingRequest namedUserSubscriptionListsListingRequest = NamedUserSubscriptionListsListingRequest.newRequest("4cbd1c1c-42e1-4606-bc93-9b707bcedcbc"); Response response = client.execute(namedUserSubscriptionListsListingRequest); ``` ```python from urbanairship import ( BasicAuthClient, SubscriptionList ) client = BasicAuthClient( key='', secret='' ) # Get subscription lists for a named user named_user_lists = SubscriptionList(client).list_by_named_user('4cbd1c1c-42e1-4606-bc93-9b707bcedcbc') ``` --- ## Subscription lists listing {#getsubscriptionlists} Provides a list of subscription lists IDs that are associated with this app key. [Jump to examples ↓](#getsubscriptionlists-examples) ### `GET /api/subscription_lists` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Responses** **`200`** Returns OK for success, with the list of subscription lists for the app. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` Success. - **`subscription_lists`** `array` <[Subscription List result object]({{< ref "/developer/rest-api/ua/schemas/subscription-lists/" >}}#subscriptionlistresultobject)> An array of subscription list result objects. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/subscription_lists HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "subscription_lists": [ { "list_id": "example_listId-1", "name": "A nice readable name 1", "scopes": ["email"], "messaging_type": "transactional", "default_opted_in": false }, { "list_id": "example_listId-2", "name": "A nice readable name 2", "description": "A very nice description for you.", "scopes": ["app", "web"], "default_opted_in": true } ] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); SubscriptionListListingRequest subscriptionListListingRequest = SubscriptionListListingRequest.newRequest(); Response response = client.execute(subscriptionListListingRequest); ``` ```python from urbanairship import ( BasicAuthClient, SubscriptionList ) client = BasicAuthClient( key='', secret='' ) # List all subscription lists subscription_lists = SubscriptionList(client).list() ``` --- # Tag Lists > Manage tag lists for organizing and applying tags in bulk. {{< note >}} You cannot update channel information or opt-in status from these endpoints. To update channels, use the appropriate channel registration endpoints. {{< /note >}} ## Create a tag list {#createtaglist} Add tags to your contacts by creating a list and uploading CSV file with user identifiers. The body of the request contains the name, description, and optional metadata for the list. After you define a list, you populate it with a call to the [Upload Tag List](/docs/developer/rest-api/ua/operations/tag-lists/#uploadtaglist) endpoint. [Jump to examples ↓](#createtaglist-examples) ### `POST /api/tag-lists` {{< important >}} You must prefix tag list names with `"ua_tags_"`. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Request body** **Content-Type:** `application/json` [Tag List metadata object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taglistmetadataobject) **Responses** **`201`** The list was created successfully. Response headers: | Name | Type | Description | |------|------|-------------| | `Location` | `string` | The URI of the list, used for later updates. | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`409`** The request conflicts with another request. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/tag-lists HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "name":"ua_tags_foobar", "description":"Description of the file being uploaded", "extra":{ "key":"value", "another":"etc..." }, "add":{ "tag-group-name":[ "tag-value" ], "tag-group-name2":[ "tag-value2a", "tag-value2b" ] }, "remove":{ "tag-group-name3":[ "tag-value" ] }, "set":{ "tag-group-name4":[ "tag-value" ] } } ``` ```http HTTP/1.1 201 Created Content-Type: application/json Location: https://go.urbanairship.com/api/tag-lists/ua_tags_foobar { "ok" : true } ``` ```python from urbanairship import ( BasicAuthClient, TagList ) client = BasicAuthClient( key='', secret='' ) tag_list = TagList( client=client, list_name="ua_tags_my_new_list", description="First of many tags lists!", extra={ "filename": "tags.csv", "source": "CRM" }, add_tags={ "tag-group-name": ["tag-value"], "tag-group-name2": ["tag-value2a", "tag-value2b"] }, remove_tags={ "tag-group-name3": ["tag-value"] }, set_tags={ "tag-group-name4": ["tag-value"] } ) tag_list.create() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: 'app_key', secret: 'master_secret') tags = {'tag_group_name': ['tag1', 'tag2']} tag_list = UA::TagList.new(client: airship) tag_list.name = 'ua_tags_list_name' tag_list.create(description: 'description', extra: {'key': 'value'}, add: tags) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TagListRequest tagListRequest = TagListRequest.newRequest() .setName("ua_tags_my_new_list"); .setDescription("First of many tags lists!") .addTags("tag_group1", ImmutableSet.of("tag1","tag2")) .removeTags("tag_group2", ImmutableSet.of("tag3","tag4")) .setTags("tag_group3", ImmutableSet.of("tag4","tag5")) .addExtra("test","value") Response response = client.execute(tagListRequest); ``` --- ## Delete tag list {#deletetaglist} Delete a list. Deleting a list will not affect any previous uploads but will prevent new uploads to the deleted list. For example, this does not remove the tags associated with the previously-uploaded file from the channels in that file. [Jump to examples ↓](#deletetaglist-examples) ### `DELETE /api/tag-lists/{list_name}` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The name of the list. | **Responses** **`204`** The delete operation was successful. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http DELETE /api/tag-lists/ua_tags_foobar HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+csv; version=3 ``` ```http HTTP/1.1 204 No Content ``` --- ## Download list errors {#gettaglisterrors} During processing, after a list is uploaded, errors can occur. Depending on the type of list processing, an error file may be created, showing a user exactly what went wrong. [Jump to examples ↓](#gettaglisterrors-examples) ### `GET /api/tag-lists/{list_name}/errors` **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The name of the list. | **Responses** **`200`** Returns OK for success. The response will contain the errors found during list processing. Response body: **Content-Type:** `text/csv` Type: `string` **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/tag-lists/ua_tags_foobar/errors HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+csv; version=3 ``` ```http HTTP/1.1 200 OK Content-Type: text/csv 8b4de669-16f1-4e71-9a1f-0c62a8235a65,ERROR,"Unknown channel" abcd,ERROR,"Invalid msisdn" ``` ```python from urbanairship import ( BasicAuthClient, TagList ) client = BasicAuthClient( key='', secret='' ) tag_list = TagList( airship=client, list_name="ua_tags_foobar", description="example list", ) errors = tag_list.get_errors() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: 'app_key', secret: 'master_secret') tag_list = UA::TagList.new(client: airship) error_csv = tag_list.errors ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TagListErrorsRequest request = TagListErrorsRequest.newRequest("ua_tags_foobar"); Response response = client.execute(request); ``` --- ## Retrieve lists {#gettaglistsmetadata} Retrieve information about all tag lists. This call returns a list of metadata that will not contain the actual lists of users. [Jump to examples ↓](#gettaglistsmetadata-examples) ### `GET /api/tag-lists` {{< note >}} The tag list content will return the data provided in the [tag list creation](/docs/developer/rest-api/ua/operations/tag-lists/#createtaglist) operation. Although `add`, `remove`, and `set` are optional, one or more must be present. {{< /note >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Responses** **`200`** Lists metadata retrieved successfully. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`lists`** `array` <[Tag List response object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taglistresponseobject)> An array of list objects. - **`ok`** `boolean` Success. **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http GET /api/tag-lists HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 ``` ```http HTTP/1.1 200 OK Data-Tag: lists Content-Type: application/vnd.urbanairship+json; version=3 { "ok" : true, "lists" : [ { "name" : "ua_tags_foo", "description" : "", "extra" : { "key": "value" }, "add":{ "tag-group-name": [ "tag-value" ], "tag-group-name2": [ "tag-value2a", "tag-value2b" ] }, "remove": { "tag-group-name3": [ "tag-value" ] }, "set": { "tag-group-name4": [ "tag-value" ] }, "created" : "2013-08-08T20:41:06", "last_updated" : "2014-05-01T18:00:27", "channel_count" : 0, "mutation_success_count": 1000, "mutation_error_count": 10, "error_path": "https://go.urbanairship.com/api/tag-lists/users_a/errors", "status" : "ready" }, { "..." : "..." } ] } ``` ```python from urbanairship import ( BasicAuthClient, TagList ) client = BasicAuthClient( key='', secret='' ) # List all tag lists response = TagList.list(airship=client) tag_lists = response.json() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: 'app_key', secret: 'master_secret') tag_list = UA::TagList.new(client: airship) list_response = tag_list.list ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TagListListingRequest tagListListingRequest = TagListListingRequest.newRequest(); Response response = client.execute(tagListListingRequest); ``` --- ## Upload tag list {#uploadtaglist} Upload a CSV that will set tag values on the specified channels or Named Users. The first entry in the uploaded CSV must be a header row. The first field must be one of the following identifier types: `channel_id`, `msisdn`, `named_user`, `email_address`. Only one identifier type is allowed per file. You must include both `msisdn` and `sms_sender` columns when targeting SMS or MMS channel types. See example to the right. Uploads must be newline-delimited identifiers (text/CSV) as described in RFC 4180, with commas as the delimiter, optionally double-quoted values, UTF-8 encoded, and with CRLF or LF line separators. | Target type | Required column headers | |------------------|------------------------------------------------------------------------------------------| | Web | `channel_id` | | Open Channel | `channel_id` | | iOS | `channel_id` | | Android | `channel_id` | | Named User | `named_user` | | Email | `email_address` | | SMS |
  • `msisdn` (numeric and no leading 0)
  • `sms_sender` (numeric)
| | MMS |
  • `msisdn` (numeric and no leading 0)
  • `sms_sender` (numeric)
| Optional Fields: Opt-in dates can optionally be set for new channels when the identifier is an `email_address` or `msisdn`. | Target type | Optional column headers | |-----------------|------------------------------------------------------------------------------------------| | SMS | `ua_opted_in` (UTC Timestamp) | | MMS | `ua_opted_in` (UTC Timestamp) | | Email |
  • `ua_transactional_opted_in` (UTC Timestamp)
  • `ua_commercial_opted_in` (UTC Timestamp)
| [Jump to examples ↓](#uploadtaglist-examples) ### `PUT /api/tag-lists/{list_name}/csv` {{< note >}} The maximum number of rows that may be uploaded to a list is 10 million. `Content-Encoding: gzip` is supported and recommended on this endpoint to reduce network traffic. {{< /note >}} {{< warning >}} If your upload times out due to a poor connection, you must re-upload the list from scratch. Because we want to ensure that the entirety of a given list is successfully uploaded, we do not support partial list uploads. {{< /warning >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): lst **Path parameters:** | Name | Type | Required | Description | |------|------|----------|-------------| | `list_name` | `string` | Required | The `name` of the list you want to retrieve or update. | **Request body** **Content-Type:** `text/csv` Type: `string` **Responses** **`202`** The request has been accepted for processing. Response body: **Content-Type:** `application/json` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** Bad Request. Parsing or validating the request failed. | Error code | Description | |---|---| | 40002 | CSV contains too many identifiers | | 40003 | CSV header contains too many columns | | 40013 | CSV header’s first field must be an identifier | | 40018 | CSV header does not contain required column for identifier type | Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`404`** The requested resource doesn't exist. Response body: **Content-Type:** `application/vnd.urbanairship+json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http PUT /api/tag-lists/ua_tags_foobar/csv HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv channel_id c543f3a3-bc1d-4830-8dee-7532c6a23b9a 6ba360a0-1f73-4ee7-861e-95f6c1ed6410 15410d17-687c-46fa-bbd9-f255741a1523 c2c64ef7-8f5c-470e-915f-f5e3da04e1df ``` ```http HTTP/1.1 202 Accepted Content-Type: application/json { "ok" : true } ``` ```python from urbanairship import ( BasicAuthClient, TagList ) client = BasicAuthClient( key='', secret='' ) tag_list = TagList( client=client, list_name="ua_tags_cool_list", description="example list" ) tag_list.upload(file_path="path/to/file.csv") ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: 'app_key', secret: 'master_secret') tag_list = UA::TagList.new(client: airship) tag_list.name = 'ua_tags_list_name' tag_list.upload(csv_file: 'file_content', gzip: true) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TagListUploadRequest tagListUploadRequest = TagListUploadRequest.newRequest("ua_tags_cool_list", "path/to/file.csv"); Response response = client.execute(tagListUploadRequest); ``` *Tag list CSV upload for SMS* ```http PUT /api/tag-lists/ua_tags_foobar/csv HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: text/csv msisdn,sms_sender,firstName 5035556789,18588675309,Jane 4155551212,18588675309,Rory ``` ```http HTTP/1.1 202 Accepted Content-Type: application/json { "ok" : true } ``` ```python from urbanairship import ( BasicAuthClient, TagList ) client = BasicAuthClient( key='', secret='' ) tag_list = TagList( client=client, list_name="ua_tags_foobar", description="example list" ) tag_list.upload(file_path="path/to/sms_file.csv") ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: 'app_key', secret: 'master_secret') tag_list = UA::TagList.new(client: airship) tag_list.name = 'ua_tags_list_name' tag_list.upload(csv_file: 'sms_file_content', gzip: true) ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); TagListUploadRequest tagListUploadRequest = TagListUploadRequest.newRequest("ua_tags_cool_list", "path/to/sms_file.csv.csv"); Response response = client.execute(tagListUploadRequest); ``` --- # Tags > Operations to assign or unassign tags for Channels and Named Users. Tags belong to Tag Groups and can help you organize channels using identifiers relevant to your operations. See the linked for information about, and strategies for using, tag groups. {{< note >}} If you previously used the `/api/tags` endpoint to set tags, it is strongly recommended that you transition to the endpoints and methods specified in this document. {{< /note >}} ## Channel tags {#modifychanneltags} Add, remove, or set tags on a channel. [Jump to examples ↓](#modifychanneltags-examples) ### `POST /api/channels/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per channel. Adding more than 1,000 tags per channel can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per channel, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Adds the specified tags to the channel. Tags that are already present are not modified/removed as a result of this operation. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** Specifies one or more channels that you want to apply tag operations to. **OBJECT PROPERTIES** - **`amazon_channel`** `array[string]` The unique channel identifier for a Fire OS device. Min items: 1, Max items: 1000 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`android_channel`** `array[string]` The unique channel identifier for an Android device. Min items: 1, Max items: 1000 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`channel`** `array[string]` The unique channel identifier for `email`, `sms`, `open`, or `web` device types. Min items: 1, Max items: 1000 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`ios_channel`** `array[string]` The unique channel identifier for an iOS device. Min items: 1, Max items: 1000 Example: `00256e0b-b02f-4f12-a77f-4c3d57078330,f59970d3-3d42-4584-907e-f5c57f5d46a1` - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Removes the specified tags from the channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Assigns a list of tags exactly. Any previously set tags that are not in this current list will be removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** Returns OK for success. If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 is returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` - **`ok`** `boolean` If true, your request was processed normally. - **`warnings`** `array[string]` Returned when some tag groups could not be updated. Contains a string indicating each tag group that could not be updated and the reason the update failed. **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/tags HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "ios_channel": "b8f9b663-0a3b-cf45-587a-be880946e881", "android_channel": "13863b3c-f860-4bbf-a9f1-4d785379b8a2" }, "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true, "warnings": ["The following tag groups do not exist: my_fav_tag_group2", "The following tag groups are deactivated: my_fav_tag_group3"] } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); ChannelTagRequest request = ChannelTagRequest.newRequest() .addIOSChannel("b8f9b663-0a3b-cf45-587a-be880946e881") .addAndroidChannel("13863b3c-f860-4bbf-a9f1-4d785379b8a2") .addTags("my_fav_tag_group1", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("my_fav_tag_group2", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("my_fav_tag_group3", ImmutableSet.of("tag1", "tag2", "tag3")); Response response = client.execute(request); ``` ```python import urbanairship as ua client = ua.BasicAuthClient('', '') channel_tags = ua.devices.ChannelTags(client) ios_audience = ['b8f9b663-0a3b-cf45-587a-be880946e881'] android_audience = ['13863b3c-f860-4bbf-a9f1-4d785379b8a2'] channel_tags.set_audience(ios_audience, android_audience ) channel_tags.add('my_fav_tag_group1', ['tag1', 'tag2', 'tag3']) channel_tags.remove('my_fav_tag_group2', 'tag4') channel_tags.send() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') channel_tags = UA::ChannelTags.new(client: airship) ios_audience = 'b8f9b663-0a3b-cf45-587a-be880946e881' android_audience = '13863b3c-f860-4bbf-a9f1-4d785379b8a2' channel_tags.set_audience( ios: ios_audience, android: android_audience ) channel_tags.add(group_name: 'my_fav_tag_group1', tags: ['tag1', 'tag2', 'tag3']) channel_tags.remove(group_name: 'my_fav_tag_group2', tags: 'tag4') channel_tags.send_request ``` --- ## Contacts tags {#modifycontacttags} Add, remove, or set tags on a Contact. A single request body may contain add and/or remove objects or a single set field. At least one of the add, remove, or set objects must be present in a request. ### `POST /api/contacts/tags/` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per Contact. Adding more than 1,000 tags per Contact can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per Contact, and they will help you find an alternative. {{< /important >}} **Security:** - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): cnt **Request body** **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Add the list of tags to the Contacts, but do not remove any. If the tags are already present, they are not modified. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** The Contacts you want to associate/disassociate tags with. **OBJECT PROPERTIES** - **`contact_id`** `array[string]` Min items: 1, Max items: 1000 - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Remove the list of tags from the Contacts, but do not remove any others. If the tags are not currently present, nothing happens. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Set these tags for the audience. Any tags previously associated with the audience tags that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 will be returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` **REQUIRED** Set to `true` when status code is `200`. - **`tag_warnings`** `string` Warnings encountered when processing tags for this Contact. **`400`** Parsing or validating the request failed. You will see this error if the same tag is present in both the add and remove fields. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) --- ## Email tags {#modifyemailchanneltags} Add, remove, or set tags for a single email channel. [Jump to examples ↓](#modifyemailchanneltags-examples) ### `POST /api/channels/email/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per channel. Adding more than 1,000 tags per channel can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per channel, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** A single request body can contain an `add` and/or `remove` field or a single `set` field. One or more of the `add`, `remove`, or `set` keys must be present in the request. **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Adds the specified tags to the channel. Tags that are already present are not modified/removed as a result of this operation. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** Specifies the email address you want to perform tag operations against. Must contain a single `email_address` key. **OBJECT PROPERTIES** - **`email_address`** `string` **REQUIRED** The email address you want to modify tags for. Accepts a single string value representing an email address. Example: `name@example.com` - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Removes the specified tags from the channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Assigns a list of tags exactly. Any previously set tags that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** Returns OK for success. If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 will be returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/email/tags HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "email_address": "name@example.com" }, "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); EmailTagRequest request = EmailTagRequest.newRequest(); emailTagRequest.addEmailChannel("name@example.com") .addTags("my_fav_tag_group1", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("my_fav_tag_group2", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("my_fav_tag_group3", ImmutableSet.of("tag1", "tag2", "tag3")); Response response = client.execute(request); ``` ```python from urbanairship import ( BearerTokenClient, EmailTags ) client = BearerTokenClient( app_key='', token='' ) # replaces all existing tags on an email channel email_tags = EmailTags(airship=client, address='name@example.com') email_tags.set(group='my_tag_group', tags=['one', 'two', 'three']) email_tags.send() # adds and removes tags from an email channel email_tags = EmailTags(airship=client, address='name@example.com') email_tags.remove(group='my_tag_group', tags=['one', 'two', 'three']) email_tags.add(group='my_tag_group', tags=['some', 'new', 'tags']) email_tags.send() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') email_tags = UA::EmailTags.new(client: airship) #set an audience email_tags.set_audience(email_address: 'name@example.com') #add a tag email_tags.add(group_name: 'my_fav_tag_group1', tags: 'tag2') #remove a tag email_tags.remove(group_name: 'my_fav_tag_group1', tags: 'tag1') email_tags.send_request ``` --- ## Named Users tags {#modifynamedusertags} Add, remove, or set tags on a Named User. A single request body may contain add and/or remove objects or a single set field. At least one of the add, remove, or set objects must be present in a request. [Jump to examples ↓](#modifynamedusertags-examples) ### `POST /api/named_users/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per Named User. Adding more than 1,000 tags per Named User can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per Named User, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAppAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAppAuth) - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): nu **Request body** **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Add the list of tags to the Named User(s), but do not remove any. If the tags are already present, they are not modified. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** The Named User(s) you want to associate/disassociate tags with. **OBJECT PROPERTIES** - **`named_user_id`** `array[string]` Min items: 1, Max items: 1000 - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Remove the list of tags from the Named User(s), but do not remove any others. If the tags are not currently present, nothing happens. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Set these tags for the audience; any tags previously associated with the audience tags that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 will be returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/json` - **`ok`** `boolean` **REQUIRED** Set to `true` when status code is `200`. - **`tag_warnings`** `string` Warnings encountered when processing tags for this Named User. **`400`** Parsing or validating the request failed. You will see this error if the same tag is present in both the add and remove fields. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`406`** Return when the client requests a version of the API that cannot be satisfied, because no compatible version is currently deployed. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/named_users/tags HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "named_user_id": [ "user-1", "user-2", "user-3" ] }, "add": { "crm": [ "tag1", "tag2", "tag3" ], "loyalty": [ "tag1", "tag4", "tag5" ] }, "remove": { "loyalty": [ "tag6", "tag7" ] } } ``` ```http HTTP/1.1 200 OK Content-Type: application/vnd.urbanairship+json; version=3 { "ok": true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); NamedUserTagRequest request = NamedUserTagRequest.newRequest() .addNamedUsers("user-1", "user-2", "user-3") .addTags("crm", ImmutableSet.of("tag1", "tag2", "tag3")) .addTags("loyalty", ImmutableSet.of("tag1", "tag4", "tag5")) .removeTags("loyalty", ImmutableSet.of("tag6", "tag7")); Response response = client.execute(request); ``` ```python from urbanairship import ( BasicAuthClient, NamedUser ) client = BasicAuthClient( key='', secret='' ) named_user = NamedUser(airship=client, named_user_id='user-1') resp1 = named_user.tag( group='loyalty', add=['tag2', 'tag3', 'tag4'], remove='tag1' ) resp2 = named_user.tag( group='crm', set=['tag5', 'tag6'] ) ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') named_user_tags = UA::NamedUserTags.new(client: airship) named_user_ids = ['user-1', 'user-2', 'user-3'] named_user_tags.set_audience(user_ids: named_user_ids) named_user_tags.add(group_name: 'crm', tags: ['tag1', 'tag2', 'tag3']) named_user_tags.remove(group_name: 'loyalty', tags: ['tag6', 'tag7']) named_user_tags.send_request ``` --- ## Open channel tags {#modifyopenchanneltags} Manipulate a single open channel’s tags. Open channels are identified by `address`, not by their `channel_id`. [Jump to examples ↓](#modifyopenchanneltags-examples) ### `POST /api/channels/open/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per channel. Adding more than 1,000 tags per channel can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per channel, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Adds the specified tags to the channel. Tags that are already present are not modified/removed as a result of this operation. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** The request body containing an address and `open_platform_name`. **OBJECT PROPERTIES** - **`address`** `string` **REQUIRED** Where notifications sent to this `channel_id` will be sent. Examples: email address, phone number. If missing, `channel_id` must be present. The `address` is one-to-one with the `channel_id`. New addresses on existing channels will overwrite old associations. Example: `new_email@example.com` - **`open_platform_name`** `string` **REQUIRED** An alphanumeric string that must be the name of a pre-created open platform object. Min length: 1, Max length: 128 Example: `twitter` - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Removes the specified tags from the channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Assigns a list of tags exactly. Any previously set tags that are not in this current list will be removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** Returns OK for success. If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 is returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/open/tags HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "address": "Number Four", "open_platform_name": "cylon" }, "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } } ``` ```http HTTP/1.1 200 Accepted Content-Type: application/vnd.urbanairship+json; version=3 { "ok":true } ``` ```java UrbanAirshipClient client = UrbanAirshipClient.newBuilder() .setKey("") .setSecret("") .build(); OpenChannelTagRequest openChannelTagRequest = OpenChannelTagRequest.newRequest() .addOpenChannel("Number Four","cyclon") .addTags("CRM_Delux", Set.of("tag1","tag2")) .removeTags("CRM_Delux", Set.of("tag3","tag4")); Response response = client.execute(openChannelTagRequest); ``` ```python from urbanairship import ( BasicAuthClient, OpenChannel ) client = BasicAuthClient( key='', secret='' ) channel = OpenChannel(airship=client) channel.address = 'Number Four' channel.open_platform = 'cylon' channel.tags = ['tag1', 'tag2', 'tag3'] response = channel.update() ``` ```ruby require 'urbanairship' UA = Urbanairship airship = UA::Client.new(key: '', secret: '') open_channel = UA::OpenChannel.new(client: airship) open_channel.opt_in = true open_channel.address = 'Number Four' open_channel.open_platform = 'cylon' open_channel.channel_id = 'df6a6b50-9843-0304-d5a5-743f246a4946' open_channel.tags = ['tag1', 'tag2', 'tag3'] open_channel.update(set_tags: true) ``` --- ## SMS tags {#modifysmschanneltags} Add, remove, or set tags for a single SMS channel. [Jump to examples ↓](#modifysmschanneltags-examples) ### `POST /api/channels/sms/tags` {{< important >}} A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. We support up to 1,000 tags per channel. Adding more than 1,000 tags per channel can cause latency and service interruptions. We strongly recommend removing unused tags whenever possible, and using Custom Events when appropriate. Please [contact Support](https://support.airship.com/) if you believe your use case requires more than 1,000 tags per channel, and they will help you find an alternative. {{< /important >}} **Security:** - [basicAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-basicAuth) - [bearerAuth]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-bearerAuth) - [oauth2Token]({{< ref "/developer/rest-api/ua/introduction/" >}}#security-oauth2Token): chn **Request body** A single request body can contain an `add` and/or `remove` field or a single `set` field. One or more of the `add`, `remove`, or `set` keys must be present in the request. **Content-Type:** `application/json` - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Adds the specified tags to the channel. Tags that are already present are not modified/removed as a result of this operation. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`audience`** `object` **REQUIRED** Specifies the MSISDN and sender you want to perform tag operations against. **OBJECT PROPERTIES** - **`msisdn`** `string` The mobile phone number corresponding to the SMS channel. Must be numeric characters only, without leading zeros. 15 digits maximum. Max length: 15 - **`sender`** `string` A long or short code the app is configured to send from. For example, `12345`. - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Removes the specified tags from the channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Assigns a list of tags exactly. Any previously set tags that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Responses** **`200`** Returns OK for success. If a tag request is partially valid, i.e., at least one tag group exists and is active, a 200 will be returned with a warning in the response about the tag groups that failed to update. The tag groups listed in the warning will be CSV-formatted. Response body: **Content-Type:** `application/vnd.urbanairship+json; version=3` [OK response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#okresponseobject) **`400`** There was a parsing or validation error in the request. Bad Request errors typically include `path` and `location` in the response to help you find the cause of the error. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`401`** Authentication information (the app key and secret or bearer token) was either incorrect or missing. Response body: **Content-Type:** `text/plain` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **`403`** Authentication was correct, but the user does not have permission to access the requested API, e.g., if the feature in question is not included in your pricing plan. Response body: **Content-Type:** `application/json` [Error response]({{< ref "/developer/rest-api/ua/schemas/responses/" >}}#error) **Examples** *Example* ```http POST /api/channels/sms/tags HTTP/1.1 Authorization: Bearer Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "audience": { "sender": "12345", "msisdn": "15035556789" }, "add": { "my_fav_tag_group1": ["tag1", "tag2", "tag3"], "my_fav_tag_group2": ["tag1", "tag2", "tag3"], "my_fav_tag_group3": ["tag1", "tag2", "tag3"] } } ``` --- #### Data Formats JSON schemas for API requests and responses. Schemas define the structure, types, and validation rules for data exchanged with the API. # Attributes > Attributes appear on channels and Named Users. You can target an audience using attribute selectors. Available attribute types are Text, Number, Date, and JSON. {{< tip >}} Use [compound selectors](/docs/developer/rest-api/ua/schemas/audience-selection/#compoundselector) to negate (NOT) or select a value range. {{< /tip >}} ## Array {#attributesarray} The array can hold string, number, boolean, objects, and array. Accepts numbers and strings for integer/number type attributes, but your string must be convertible to a number or the request will fail. Objects must be valid JSON or the request will fail. **Array items — One of:** - [Array]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#attributesarray) --- ## Attribute assignment {#attributesobject} [Jump to examples ↓](#attributesobject-examples) - **`attributes`** `array` **REQUIRED** The attributes that you want to set for, or remove from, your `audience`. You can have both `set` and `remove` actions in the same request. Min items: 1 **One of:** - [Set Attribute]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#setattributeobject) Add a new attribute, or edit the value of an existing attribute, for the audience. - [Remove Attribute]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#removeattributeobject) Remove an existing attribute from the audience. **Used in:** - [Named User update]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#updatenameduser) - [Set or remove attributes on a Contact]({{< ref "/developer/rest-api/ua/operations/contacts/" >}}#modifycontactattributes) - [Set or remove attributes on channels]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelattributes) - [Set or remove attributes on Named Users]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#modifynameduserattributes) **Examples** *Attributes assignment* ```json { "attributes": [ { "action": "remove", "key": "minor_league" }, { "action": "set", "key": "position", "value": "LF" } ] } ``` --- ## Custom and predefined Attributes {#attributes} Attributes associated with a channel or Named User. This object contains predefined attributes that you enable and assign to the channel, or custom attributes that you create and assign. This object enumerates predefined attributes, but you can [create your own in the Airship dashboard](/docs/guides/audience/attributes/adding/). [Jump to examples ↓](#attributes-examples) - **`account_creation`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the user created their account. Format: `date-time` - **`advertising_id`** `string` The IDFA associated with a user. - **`age`** `integer` The user's age. - **`altitude`** `number` The altitude associated with a user. - **`birthdate`** `string` The user's birthdate. - **`city`** `string` The city associated with the user. - **`company`** `string` The company that a user is associated with. - **`country`** `string` The country associated with the user. - **`email`** `string` A user's email address. - **`first_name`** `string` The first name of a user. - **`full_name`** `string` A user's first and last names. - **`gender`** `string` A user's gender. - **`home_phone`** `integer` The user's home phone number — similar to an SMS channel `msisdn`. - **`last_name`** `string` The last name of a user. - **`latitude`** `number` The latitude associated with a user — maybe their default location. - **`longitude`** `number` The longitude associated with a user — maybe their default location. - **`loyalty_tier`** `string` The loyalty program tier that a user is associated with, e.g., gold, platinum, etc. - **`mobile_phone`** `integer` The user's mobile phone number — similar to an SMS channel `msisdn`. - **`region`** `string` The state, province, principality, etc. associated with the user. - **`title`** `string` A default attribute. You must enable this attribute in the dashboard before you can assign it. - **`username`** `string` A user's username — generally a part of their login information. - **`work_phone`** `integer` The user's work phone number — similar to an SMS channel `msisdn`. - **`zipcode`** `integer` A user's zipcode. This is different from the SMS channel `ua_ndc` attribute, that records user's area code or phone number prefix. - **`*`** `object` **One of:** - `string` - `number` - `integer` **Used in:** - [Channel listing]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannels) - [Channel lookup]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannel) - [Look up an email address]({{< ref "/developer/rest-api/ua/operations/email/" >}}#getemailchannel) - [Named User listing or lookup]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#getnameduser) - [SMS channel lookup]({{< ref "/developer/rest-api/ua/operations/sms/" >}}#getsmschannel) **Examples** *Example Attributes object* ```json { "device_attributes": { "ua_device_os": "10", "ua_country": "US", "ua_device_model": "SM-G973U", "ua_local_tz": "America/Los_Angeles", "ua_app_version": "2020-02-01T002322-goat", "ua_location_settings": "true", "ua_language": "en", "ua_sdk_version": "13.1.0", "ua_carrier": "Verizon " }, "attributes": { "first_name": "Cool", "last_name": "Person", "birthdate": "1983-03-15T00:00:00", } } ``` --- ## Date Attribute selector {#dateattribute} An attribute object with a `DATE` schema type. Performs absolute date comparisons for ISO-formatted date values or a relative date comparisons given an integer `value` and `precision`, e.g., `days`, `months`. Use a date attribute to target a channel or Named User based on the date values. [Jump to examples ↓](#dateattribute-examples) - **`attribute`** `string` **REQUIRED** The key for the date attribute that you previously defined in the Airship UI, e.g., `"birth_date"`. Min length: 1, Max length: 256 - **`operator`** `string` **REQUIRED** The operator used to evaluate the attribute expression. The `operator` that you use with a date attribute will determine which additional properties will be required in the object. See table for required fields. | Operator | Required properties | |---|---| | `is_empty` | `attribute` | | `before` | `attribute`, `value`, `precision`\* | | `after` | `attribute`, `value`, `precision`\* | | `range` | `attribute`, `value` | | `equals` | `attribute`, `value`, `precision`\*\* | \* *`precision` is required, but enum values are different than with an equals operator* \*\* *`precision` is required, but enum values are different than with a before or after operator* **Date Attribute Operators**: * `is_empty`— Evaluates to true if a channel or Named User does not have a value for the attribute. * `before`— Value is one of: - *String*, ISO 8601 inclusive date, optionally including an offset, e.g., `2007-03-01T13:00:00+08:00`. The value will be converted and stored as UTC. - *Integer*, Relative number of units from the current time (i.e., now) into the past. Example: `"before": 20` indicates "at least 20 years ago" given a `precision` of `years`. - *String* with the value `"now"`, representing the current date-time, i.e., "before now". When using the `now` value, no `precision` is required. **Note**: When using the `before` operator, precision value must be one of `years`, `months`, `days`, `hours`, or `minutes`. * `after`— Values for `after` behave identically to `before`, as described above. * `range`— An ISO 8601 time interval. The format consists of an inclusive start and an exclusive end time date separated with a `/`, e.g., `2019-03-01T13:00:00/2019-05-11T15:30:00`. `range` does not have a precision. * `equals`— allows for selecting specific or non-specific dates as determined by the `precision` provided in the attribute object. **Note**: When using the `equals` operator, `precision` must be one of: - `day` — an integer which represents the day of the month or "now". - `month` — an integer which represents the month of the year starting with 1 for Jan or "now" which will use the value of the current month. - `month_day` — a string in the format of "mm-dd" which represents a month and day. Ex. 05-04 is May 4th. Value can also be "now". If today is 2020-03-09, then value will be "03-09". - `year_month` — a string in the format of "yyyy-mm" which represents a year and month. Ex. 2020-05 is May 2020. Value can also be "now". If today is 2020-03-09, then value will be "2020-03". - `year_month_day` — a string in the format of "yyyy-mm-dd" which represents a specific year, month, and day. Ex. 2020-05-04. Value can also be "now". If today is 2020-03-09, then value will be "2020-03-09". - or value can be "now" which is the current date-time. Possible values: `is_empty`, `before`, `after`, `range`, `equals` - **`precision`** `string` The precision, expressed as a timing interval unit, that Airship uses to evaluate a date attribute expression. Possible values: `years`, `months`, `days`, `hours`, `minutes`, `day`, `month`, `month_day`, `year_month`, `year_month_day` - **`relative_to`** `string` Specifies whether the date is in the `future` or in the `past`. If missing, it defaults to `past`. Possible values: `future`, `past` - **`value`** `object` **One of:** - `string` A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format). - `integer` An integer specifying the relative number of units, e.g., `days`, `years`, from the current time into the past. **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#createsegment) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Segment lookup]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#getsegment) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Subscribe or unsubscribe channels to/from subscription lists]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelsubscriptions) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Update Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#updatesegment) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) **Examples** *Date Attribute example* ```json { "audience": { "attribute": "birth_date", "operator": "equals", "precision": "month_day", "value": "05-04" } } ``` *Add four days to the current date* ```json { "audience": { "attribute": "day_of_travel", "operator": "equals", "value": "4", "precision": "days", "relative_to": "future" } } ``` *Compound selector using before and after date operators* ```json { "audience": { "AND": [ { "attribute": "birth_date", "operator": "after", "value": 55, "precision": "years" }, { "attribute": "birth_date", "operator": "before", "value": 40, "precision": "years" } ] }, "device_types": [ "android" ], "notification": { "alert": "Hello, Generation X!" } } ``` *Audience who purchased jeans* ```json { "audience": { "attribute": "item_purchased", "operator": "contains", "value": "jeans" } } ``` *Audience who did not purchase jeans* ```json { "audience": { "NOT":{ "attribute": "item_purchased", "operator": "contains", "value": "jeans" } } } ``` *Audience who did not make any purchase* ```json { "audience": { "attribute": "item_purchased", "operator": "is_empty", } } ``` *Integer value range* ```json { "audience": { "AND":[ { "attribute": "size", "operator": "greater", "value":12 }, { "attribute": "size", "operator": "less", "value": 15 } ] } } ``` --- ## Device Attributes {#device-attributes} Native attribute properties that Airship gathers automatically assigns to a channel. Varies by channel type. See: [Default Attributes](/docs/reference/data-collection/attributes/#default-attributes). For segmentation, when using `ua_app_version`, `ua_sdk_version`, or `ua_device_os`, only semantic versioning formatting is accepted, and anything after the third decimal place is excluded, e.g., `12.2.3-alpha` is compared as `12.2.3`. You can use operators `equals`, `contains`, `less`, `greater`, `is_empty` with values in the formats `1`, `1.2`, `1.2.3`. - **`ua_app_version`** `string` The app version that the channel uses. - **`ua_browser_name`** `string` The browser associated with a web channel. - **`ua_browser_type`** `string` The browser type associated with a web channel. Possible values: `mobile`, `desktop` - **`ua_browser_version`** `string` The browser version associated with a web channel. - **`ua_carrier`** `string` The cellular carrier of the device associated with an app channel. - **`ua_country`** `string` The 2-letter country code for an app or web channel. - **`ua_country_code`** `string` The country dialing code derived from the MSISDN associated with an SMS channel. - **`ua_device_model`** `string` The model of the device associated with an app channel. - **`ua_device_os`** `string` The operating system of the device associated with an app channel. - **`ua_language`** `string` The 2-letter language code for an app or web channel. - **`ua_local_tz`** `string` The time zone that the SDK registers for an app or web channel. - **`ua_location_settings`** `string` If `true`, location settings are enabled for an app channel. Possible values: `true`, `false` - **`ua_ndc`** `string` The National Destination Code aka area code derived from the MSISDN on an SMS channel. - **`ua_rcs_enabled`** `string` Rich Communication Services (RCS) capability for an SMS channel. Set to `true` when an RCS upgrade delivery receipt is received. Possible values: `true` - **`ua_sdk_version`** `string` The Airship SDK version associated with an app or web channel. - **`ua_subdivision`** `string` The ISO 3166-2 code derived from the MSISDN on an SMS channel. **Used in:** - [Channel listing]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannels) - [Channel lookup]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannel) - [Look up an email address]({{< ref "/developer/rest-api/ua/operations/email/" >}}#getemailchannel) - [Named User listing or lookup]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#getnameduser) - [SMS channel lookup]({{< ref "/developer/rest-api/ua/operations/sms/" >}}#getsmschannel) --- ## JSON Attribute selector {#jsonattribute} An attribute object with a `JSON` schema type. Performs value comparisons based on the JSON value for an attribute on a channel or Named User. [Jump to examples ↓](#jsonattribute-examples) - **`attribute`** `string` **REQUIRED** The name of the attribute. Min length: 1, Max length: 1024 - **`where`** `object` **REQUIRED** An object that filters on the JsonPath expression that you provide. **OBJECT PROPERTIES** - **`compare_as`** `string` Selects the property type for comparison. Possible values: `text`, `number`, `date`, `boolean` - **`operator`** `string` **REQUIRED** The operator used to evaluate the attribute expression. If the JsonPath expression maps to an array, the only available operators are `is_empty`, `not_empty`, `contains`, or `not_contains`. Possible values: `equals`, `contains`, `not_contains`, `less`, `less_eq`, `greater`, `greater_eq`, `range`, `before`, `after`, `is_empty`, `not_empty` - **`precision`** `string` Used only for date values. Possible values: `minutes`, `days`, `months`, `years` - **`property`** `string` **REQUIRED** The JsonPath expression that will be used to look up the value in a predefined attribute, for example `"$.x['store']['book'][0]['title']"`. This is different from selecting based on primitive string attributes, because the JsonPath expression can map to a single attribute or an array of attributes. See [JsonPath](https://github.com/json-path/JsonPath) for more information about JsonPath expressions and usage. - **`relative_to`** `string` Used only for date values. Possible values: `future`, `past` - **`value`** `object` The value of the property you are filtering for in the `where` object. Use `compare_as` to select the type for comparison. This is required for all operators except `is_empty` and `not_empty`. **One of:** - `string` - `number` - `boolean` **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#createsegment) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Segment lookup]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#getsegment) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Subscribe or unsubscribe channels to/from subscription lists]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelsubscriptions) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Update Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#updatesegment) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) **Examples** *JSON Attribute examples* ```json { // Example 1 "audience": { "attribute": "books_on_books", "where": { "property": "$.x.store.book[*].title", "operator": "equals", "value": "Dracula", "compare_as": "text" } } } { // Example 2 "audience": { "attribute": "oh_look_a_book", "where": { "property": "$.x['store']['book'][0]['title']", "operator": "equals", "value": "Dracula", "compare_as": "text" } } } { // Example 3 "audience": { "attribute": "another_one", "where": { "property": "$.x.store.codes[*].sneakers", "operator": "equals", "value": 178394549, "compare_as": "number" } } } { // Example 4 "audience": { "attribute": "and_one_more", "where": { "property": "$.x['store']['codes'][0]['available']", "operator": "equals", "value": "true", "compare_as": "boolean" } } } ``` --- ## NPS survey Attributes {#npssurveyattributes} Attributes automatically generated by Airship based on data from your NPS surveys. - **`ua_nps_category`** `string` A category based on the score a user submits in an NPS survey. Scores of 9 and 10 are categorized as `promoter`, 7 and 8 are categorized as `passive`, and 0-6 are `detractor`. - **`ua_nps_score`** `number` The score (0-10) a user submits in an NPS (Net Promoter Score) survey. --- ## Number Attribute selector {#numberattribute} An attribute object with a `NUMBER` schema type. Performs value comparisons based on the number value for an attribute on a channel or Named User. [Jump to examples ↓](#numberattribute-examples) - **`attribute`** `string` **REQUIRED** The key for the number attribute that you previously defined in the Airship UI, e.g., `"lifetime_value"`. Min length: 1, Max length: 256 - **`operator`** `string` **REQUIRED** The operator used to evaluate the attribute expression. Possible values: `equals`, `contains`, `less`, `greater`, `is_empty` - **`value`** `number` **REQUIRED** The value of the number attribute that you are targeting. For example, `15000`. **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#createsegment) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Segment lookup]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#getsegment) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Subscribe or unsubscribe channels to/from subscription lists]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelsubscriptions) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Update Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#updatesegment) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) **Examples** *Number Attribute example* ```json { "audience": { "attribute": "lifetime_value", "operator": "greater", "value": 15000 } } ``` --- ## Remove Attribute {#removeattributeobject} Remove an existing attribute from the audience. [Jump to examples ↓](#removeattributeobject-examples) - **`action`** `string` **REQUIRED** Indicate that you want to `remove` an attribute from the audience. Possible values: `remove` - **`key`** `string` **REQUIRED** The attribute ID for the attribute you want to set. JSON attribute key values must be in format `#`. See [JSON Attributes](/docs/guides/audience/attributes/about/#json-attributes) in *About Attributes*. Max length: 64 - **`timestamp`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the attribute changed. If you don't enter a timestamp, Airship uses the current time. Format: `date-time` **Used in:** - [Named User update]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#updatenameduser) - [Set or remove attributes on a Contact]({{< ref "/developer/rest-api/ua/operations/contacts/" >}}#modifycontactattributes) - [Set or remove attributes on channels]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelattributes) - [Set or remove attributes on Named Users]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#modifynameduserattributes) **Examples** *Remove Attribute* ```json { "action": "remove", "key": "minor_league" } ``` --- ## Set Attribute {#setattributeobject} Add a new attribute, or edit the value of an existing attribute, for the audience. [Jump to examples ↓](#setattributeobject-examples) - **`action`** `string` **REQUIRED** Indicate that you want to `set` an attribute on the audience. Possible values: `set` - **`key`** `string` **REQUIRED** The attribute ID for the attribute you want to set. JSON attribute key values must be in format `#`. See [JSON Attributes](/docs/guides/audience/attributes/about/#json-attributes) in *About Attributes*. Max length: 64 - **`timestamp`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the attribute changed. If you don't enter a timestamp, Airship uses the current time. Format: `date-time` - **`value`** `object` **REQUIRED** The value that you want to set for an attribute. Accepts numbers and strings for integer/number type attributes, but your string must be convertible to a number or the request will fail. You can also set an object, which must be valid JSON or the request will fail. **One of:** - `string` - `number` - - **`exp`** `number` The JSON attribute expiration date, set as the number of seconds since the epoch (January 1st, 1970). After expiration, Airship ignores the Attribute where used in segmentation and personalization. If omitted, Airship automatically sets a value of 90 days from the current date and time. The maximum expiry delay for a JSON Attribute is 731 days. **Used in:** - [Named User update]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#updatenameduser) - [Set or remove attributes on a Contact]({{< ref "/developer/rest-api/ua/operations/contacts/" >}}#modifycontactattributes) - [Set or remove attributes on channels]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelattributes) - [Set or remove attributes on Named Users]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#modifynameduserattributes) **Examples** *Set Attribute with string value* ```json { "action": "set", "key": "position", "value": "LF" } ``` *Set JSON Attribute with its required object value* ```json { "action": "set", "key": "position#instance_42", "value": { "exp": 1731531110, "name": "LeftField", "rank": 2, "active" true, "extras": [ "rookie", "mvp" ] } } ``` --- ## Text Attribute selector {#textattribute} An attribute object with a `TEXT` schema type. Evaluates for the inclusion or exclusion of a text (string) attribute on a channel or Named User. [Jump to examples ↓](#textattribute-examples) - **`attribute`** `string` **REQUIRED** The key for the text attribute that you previously defined in the Airship UI, e.g., `"item_purchased"`. Min length: 1, Max length: 256 - **`operator`** `string` **REQUIRED** The operator used to evaluate the attribute expression. Possible values: `equals`, `contains`, `less`, `greater`, `is_empty` - **`value`** `string` **REQUIRED** The string you want to match when evaluating the attribute expression, e.g., `"jeans"`. Max length: 255 **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#createsegment) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Segment lookup]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#getsegment) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Subscribe or unsubscribe channels to/from subscription lists]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelsubscriptions) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Update Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#updatesegment) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) **Examples** *Text Attribute example* ```json { "audience": { "attribute": "item_purchased", "operator": "contains", "value": "jeans" } } ``` --- # Audience limits > Schemas for audience limits, additional audience checks, and ban list parameters. ## Audience limits object {#audiencelimitsobject} Defines limits to be applied to Push Notifications and standard in-app messages (not In-App Automations or Scenes) only. See [Audience Limit](/docs/guides/messaging/messages/delivery/delivery/#audience-limit) in the *Message delivery* user guide for additional information and limitations. [Jump to examples ↓](#audiencelimitsobject-examples) - **`max_recipients`** `integer` The maximum number of recipients a push can be delivered to. **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create pipeline (automated message)]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#createpipeline) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [Individual pipeline lookup]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#getpipeline) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List existing pipelines]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#getpipelines) - [List filtered pipelines]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#getfilteredpipelines) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Send message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#bulksendpush) - [Update pipeline]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#updatepipeline) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) - [Validate message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#validatebulksendpush) - [Validate pipeline]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#validatepipeline) **Examples** *Audience limits* ```json { "options": { "audience_limits": { "max_recipients": 1000 } } } ``` --- ## Ban List parameters {#banlistparametersobject} A list of parameters, where the key and value are both strings, that will be used to override the default values set for variables in a [Ban List](/docs/guides/audience/segmentation/ban-lists/) request URL. [Jump to examples ↓](#banlistparametersobject-examples) - **`*`** `string` Example: `[object Object]` **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create pipeline (automated message)]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#createpipeline) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [Individual pipeline lookup]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#getpipeline) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List existing pipelines]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#getpipelines) - [List filtered pipelines]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#getfilteredpipelines) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Send message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#bulksendpush) - [Update pipeline]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#updatepipeline) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) - [Validate message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#validatebulksendpush) - [Validate pipeline]({{< ref "/developer/rest-api/ua/operations/automation/" >}}#validatepipeline) **Examples** *Ban List parameters* ```json { "ban_list_parameters": { "category": "api-cat" } } ``` --- # Audience selection > Objects that help you select and target an audience. ## Atomic selector {#atomicselector} Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. [Jump to examples ↓](#atomicselector-examples) **One of:** - `string` The simplest selector, which targets the entire audience. - **Tag selector** `object` A tag is an arbitrary bit of metadata used for targeting devices. A tag specifier may or may not have an associated group declaration, indicating a `tag group` the tag belongs to, for example, `{"tag": "silver-member", "group": "loyalty"}`. If no tag group is specified, the default `device` group is used. - **`group`** `string` - **`tag`** `object` **REQUIRED** **One of:** - `string` - `array` - **Segment selector** `object` The Segment ID. - **`segment`** `object` **REQUIRED** **One of:** - `string` - `array` - **Channel selector** `object` The unique channel identifier used to target an open channel device or web device, i.e., web browser. - **`channel`** `object` **REQUIRED** **One of:** - `string` - `array` - **Named User selector** `object` A `named_user` is an alternate, non-unique name, mapped to a user profile in a different database, e.g., CRM, that can be used to target devices associated with that profile. - **`named_user`** `object` **REQUIRED** **One of:** - `string` - `array` - **Fire OS channel selector** `object` The unique channel identifier used to target a Fire OS device. - **`amazon_channel`** `object` **REQUIRED** **One of:** - `string` - `array` - **Android channel selector** `object` The unique channel identifier used to target an Android device. - **`android_channel`** `object` **REQUIRED** **One of:** - `string` - `array` - **Open channel selector** `object` The unique channel identifier used to target a device on an open platform. - **`open_channel`** `object` **REQUIRED** **One of:** - `string` - `array` - `string` A long or short code the app is configured to send from. For example, `12345`. - **SMS ID selector** `object` Selects a single SMS device. The `msisdn` must be `opted_in` to receive notifications. - **`msisdn`** `string` **REQUIRED** The recipient phone number. Min length: 1, Max length: 128 - **`sender`** `string` **REQUIRED** The sender that the app is configured to send SMS messages from. Min length: 1, Max length: 128 - **Static list selector** `object` A `static_list` is a subset of your audience defined by a CSV file containing Channel IDs or Named Users. - **`static_list`** `object` **REQUIRED** **One of:** - `string` - `array` - **Subscription List selector** `object` An single instance or array of subscription list IDs. - **`subscription_list`** `object` **REQUIRED** **One of:** - `string` - `array` - [Text Attribute selector]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#textattribute) An attribute object with a `TEXT` schema type. Evaluates for the inclusion or exclusion of a text (string) attribute on a channel or Named User. - [Number Attribute selector]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#numberattribute) An attribute object with a `NUMBER` schema type. Performs value comparisons based on the number value for an attribute on a channel or Named User. - [Date Attribute selector]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#dateattribute) An attribute object with a `DATE` schema type. Performs absolute date comparisons for ISO-formatted date values or a relative date comparisons given an integer `value` and `precision`, e.g., `days`, `months`. Use a date attribute to target a channel or Named User based on the date values. - [JSON Attribute selector]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#jsonattribute) An attribute object with a `JSON` schema type. Performs value comparisons based on the JSON value for an attribute on a channel or Named User. - **Alias selector** `object` A legacy mechanism used for mapping devices to a customer ID, e.g., a CRM identifier. Superseded by `named_user`. - **`alias`** `object` **REQUIRED** **One of:** - `string` - `array` - **APID selector** `object` A legacy identifier for targeting Android and Windows devices, superseded by `android_channel`. - **`apid`** `object` **REQUIRED** **One of:** - `string` - `array` - [Activity audience object]({{< ref "/developer/rest-api/ua/schemas/event-segmentation/" >}}#activityobject) The `activity` object defines the target audience based on lifecycle actions or Custom Event activity, using comparison operators on activity count and recency. Optionally include a `where` object, which filters for specific activity values. In the example to the right, the target audience is users who have opened your app from a notification from the "neowise" campaign at least twice, 3 days ago. - `string` A special selector used in Pipelines to indicate that the audience of the push is composed of the device or devices that activated the trigger. See [Pipeline objects](/docs/developer/rest-api/ua/schemas/pipeline-objects/) for more information. **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#createsegment) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Segment lookup]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#getsegment) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Subscribe or unsubscribe channels to/from subscription lists]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelsubscriptions) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Update Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#updatesegment) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) **Examples** *Example audience selection by tag* ```json { "audience": { "tag": "sfGiants", "group": "favorite_teams" } } ``` *Example SMS channel audience* ```json { "audience" : { "sms_id" : { "sender" : "12345", "msisdn" : "15552243311" } } } ``` *Example audience segment* ```json { "audience" : { "segment" : "" } } ``` *Example audience of Named Users* ```json { "audience" : { "named_user" : "user-id-54320" } } ``` *Example audience of static list* ```json { "audience" : { "static_list" : "name_of_list" } } ``` --- ## Audience selector (max 100) {#audienceselector100} An audience selector forms the expression that determines the set of channels to target. **One of:** - [Compound selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#compoundselector) Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. - [Atomic selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#atomicselector) Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. **Used in:** - [Subscribe or unsubscribe channels to/from subscription lists]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelsubscriptions) --- ## Audience selector (max 1000) {#audienceselector1000} An audience selector forms the expression that determines the set of channels to target. **One of:** - [Compound selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#compoundselector) Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. - [Atomic selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#atomicselector) Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) --- ## Compound selector {#compoundselector} Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. [Jump to examples ↓](#compoundselector-examples) **One of:** - **AND selector** `object` AND selector - **`AND`** `array` Min items: 1, Max items: 10 **One of:** - [Compound selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#compoundselector) Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. - [Atomic selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#atomicselector) Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. - **OR Selector** `object` OR selector - **`OR`** `array` Min items: 1, Max items: 10 **One of:** - [Compound selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#compoundselector) Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. - [Atomic selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#atomicselector) Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. - **NOT Selector** `object` NOT selector - **`NOT`** `object` **One of:** - [Compound selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#compoundselector) Compound selectors combine boolean operators (AND, OR, or NOT) with atomic or nested compound selectors. - [Atomic selector]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#atomicselector) Atomic selectors are the simplest way to identify a single device, i.e., app or browser installation, or a group of devices. These selectors are either a unique identifier for the device such as a Channel ID or metadata that maps to the device (or multiple devices) such as a tag. **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#createsegment) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Segment lookup]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#getsegment) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Subscribe or unsubscribe channels to/from subscription lists]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelsubscriptions) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Update Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#updatesegment) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) **Examples** *Example with implicit `OR`* ```json { "audience" : { "tag" : ["apples", "oranges", "bananas"] } } ``` *Example with nested selectors* ```json { "audience": { "AND": [ {"OR": [ {"tag": "sports"}, {"tag": "entertainment"} ]}, {"tag": "language_en"} ] } } ``` *Example `NOT` selector* ```json { "audience": { "AND": [ { "tag": "Federer fan" }, { "NOT": { "tag": "Messi fan" } } ] } } ``` --- # Bulk sending > Schemas for bulk sending operations, including scheduled bulk sends. Bulk sending allows you to target recipients by providing audience identifiers at send time. ## Bulk send object {#bulksendobject} A bulk send object describes everything about a [Send message with bulk ID](/docs/developer/rest-api/ua/operations/bulk-sending/#bulksendpush) or [Schedule message with bulk ID](/docs/developer/rest-api/ua/operations/bulk-sending/#schedulebulksendpush) notification. The acceptable fields are identical to a standard push with two exceptions. The audience field can only be a single `bulk_id` and there can only be one `device_type`. [Jump to examples ↓](#bulksendobject-examples) - **`audience`** `object` **REQUIRED** **OBJECT PROPERTIES** - **`bulk_id`** `string` **REQUIRED** A unique string obtained from the [Create bulk send audience operation](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) to target an audience for bulk sending. Format: `uuid` - **`campaigns`** `object` <[Campaigns object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#campaignsobject)> An object specifying custom campaign categories related to the notification. - **`device_types`** `array[string]` **REQUIRED** An array containing exactly one targeted platform. Min items: 1, Max items: 1 Possible values: `android`, `amazon`, `ios`, `web`, `sms`, `mms`, `email`, `open::open_platform_name` - **`feed_references`** `object` <[Feed references object]({{< ref "/developer/rest-api/ua/schemas/external-data-feeds-references/" >}}#feedreferences)> An object used to indicate that an external data feed should be invoked, the name of the feed to invoke, and the way in which to invoke it. You can only include a feed if you include a `templates` object in the payload or set the `personalization` option to `true`. - **`global_attributes`** `object` The global attributes object may contain an arbitrary set of keys and values, including arrays and nested objects, which will be added to the global attributes rendering namespace for this push. Top-level keys must start with a letter and cannot start with the reserved sequence ``ua_``. If the global attributes object is nonempty, it implies the ``personalization: true`` option. - **`in_app`** `object` <[In-app message]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#inappobject)> A JSON object describing an in-app message payload. - **`localizations`** `array` <[Localization object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#localization)> An array of localizations. Channels bearing the specified language/country combination will receive the corresponding message. - **`message`** `object` **One of:** - [Message Center object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#messageobject) A Message Center message. - [Message Center with template]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#messageobjectwithtemplate) Use a `template` with a message center message. You can reference a template by ID, or use `{{handlebars}}` directly in your message. - **`message_type`** `string` <[Message type]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#messagetype)> Indicates the purpose of a message. Possible values: `transactional`, `commercial` - **`notification`** `object` <[Notification object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#notificationobject)> The notification payload that is required unless either `message` or `in_app` is present. You can provide an `alert` and any platform overrides that apply to the `device_type` platforms you specify. - **`options`** `object` <[Push options]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#pushoptions)> A JSON dictionary for specifying non-payload options related to the delivery of the push. - **`orchestration`** `object` An object used to indicate the strategy to employ when deciding which channels to target for a contact. An orchestration object can be stored in Airship as the default strategy. If the orchestration section is included in a push payload, it will override the configured default value. The overall default strategy is `fan_out`. **OBJECT PROPERTIES** - **`channel_priority`** `array[string]` An array of channel types in priority order. Required if `type` is set to `channel_priority`. - **`type`** `string` **REQUIRED** The name of the orchestration strategy to employ. Possible values: `channel_priority`, `fan_out`, `triggering_channel`, `last_active` - **`snippet_references`** `object` <[Snippet references object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#snippetreferences)> An object used to indicate that a set of snippets should be loaded for use in message content. Use the following syntax in your payload: `{{> your_snippet_name }}` to reference the snippet content within a notification or rich message. See [Snippets](/docs/guides/personalization/content/snippets/) to see how to create a snippet in the Airship dashboard. **Used in:** - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) - [Send message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#bulksendpush) - [Validate message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#validatebulksendpush) **Examples** *Bulk send object* ```json { "audience" : { "bulk_id" : "36d5a261-0454-40f5-b952-942c4b2b0f22" }, "device_types" : [ "open::rcs" ], "notification" : { "alert" : "Welcome to the winter sale!!" }, "campaigns": { "categories": ["winter sale", "west coast"] } } ``` --- ## Scheduled bulk send object {#scheduledbulksendobject} A scheduled bulk send object wraps a [bulk send object](/docs/developer/rest-api/ua/schemas/others/#bulksendobject). It describes when the notification should be sent, an optional name for the notification, and the object defining the notification itself, which must be a bulk send object or [Templated message content](/docs/developer/rest-api/ua/schemas/others/#templatedmessagecontent). The scheduled date must be within 60 days. [Jump to examples ↓](#scheduledbulksendobject-examples) - **`name`** `string` A name for the scheduled push message. - **`push`** `object` **REQUIRED** **One of:** - [Bulk send object]({{< ref "/developer/rest-api/ua/schemas/bulk-sending/" >}}#bulksendobject) A bulk send object describes everything about a [Send message with bulk ID](/docs/developer/rest-api/ua/operations/bulk-sending/#bulksendpush) or [Schedule message with bulk ID](/docs/developer/rest-api/ua/operations/bulk-sending/#schedulebulksendpush) notification. The acceptable fields are identical to a standard push with two exceptions. The audience field can only be a single `bulk_id` and there can only be one `device_type`. - [Templated message content]({{< ref "/developer/rest-api/ua/schemas/bulk-sending/" >}}#templatedmessagecontent) Customers may use a template to specify message content instead of using static specification. The request format is consistent with Template Schemes. See description [Platform Override Templates](/docs/developer/rest-api/ua/schemas/platform-overrides-with-templates/). All columns (for CSV) or keys (for JSON) not prefixed with `ua_` are considered merge fields. Prefixed columns/keys are not usable in template evaluation. If the value of a delivery variable is also needed in the template, the requester should duplicate it into an unprefixed column. No verification is done in this API that the provided set of merge values matches the fields of the template. Customers using the UI will pass through a step where they'll be alerted that some template field has no matching column in the uploaded CSV. Custom Create and Send fields are not limited to strings and can contain numbers, booleans, arrays, hierarchical JSON, etc. Merge fields are allowed to use nested property names in CSV upload headers by using a subset of legal [Handlebars](/docs/guides/personalization/handlebars/) template expression syntax. - **`schedule`** `object` **REQUIRED** As defined by the [Schedule object](/docs/developer/rest-api/ua/schemas/schedules/#scheduleobject), but only the `scheduled_time` key is valid. **OBJECT PROPERTIES** - **`scheduled_time`** `string` **REQUIRED** The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when you want to perform your Create and Send operation. Users will receive the notification as soon as possible after the specified date-time. Format: `date-time` **Used in:** - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) **Examples** *Scheduled bulk send object* ```json { "schedule": { "scheduled_time" : "2024-11-07T12:00:00" }, "name" : "scheduled bulk send", "push" : { "audience" : { "bulk_id" : "36d5a261-0454-40f5-b952-942c4b2b0f22" }, "device_types" : [ "open::rcs" ], "notification" : { "alert" : "Hope you voted" }, "campaigns": { "categories": ["midterms2024", "getoutthevote2024"] } } } ``` --- ## Templated message content {#templatedmessagecontent} Customers may use a template to specify message content instead of using static specification. The request format is consistent with Template Schemes. See description [Platform Override Templates](/docs/developer/rest-api/ua/schemas/platform-overrides-with-templates/). All columns (for CSV) or keys (for JSON) not prefixed with `ua_` are considered merge fields. Prefixed columns/keys are not usable in template evaluation. If the value of a delivery variable is also needed in the template, the requester should duplicate it into an unprefixed column. No verification is done in this API that the provided set of merge values matches the fields of the template. Customers using the UI will pass through a step where they'll be alerted that some template field has no matching column in the uploaded CSV. Custom Create and Send fields are not limited to strings and can contain numbers, booleans, arrays, hierarchical JSON, etc. Merge fields are allowed to use nested property names in CSV upload headers by using a subset of legal [Handlebars](/docs/guides/personalization/handlebars/) template expression syntax. [Jump to examples ↓](#templatedmessagecontent-examples) - **`template`** `object` **One of:** - [Create and Send to email channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#email) The payload for a Create and Send operation to email channels. When sending to email channels, `device_types` must be set to `email`. - [Create and Send to SMS channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#sms) The payload for a Create and Send operation to SMS channels. When sending to SMS channels, `device_types` must be set to `sms`. - [Create and Send MMS notification]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#mms) The payload for a Create and Send operation that sends a multimedia payload (MMS) to SMS channels. When sending an MMS payload, `device_types` must be set to `mms`. - [Create and Send to open channels]({{< ref "/developer/rest-api/ua/schemas/create-and-send/" >}}#open) The payload for a Create and Send operation to open channels. When sending to open channels, the `device_type` must be set to `open::`. **Used in:** - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) **Examples** *Example templated Send a message with bulk ID* ```json { "audience" : { "bulk_id" : "36d5a261-0454-40f5-b952-942c4b2b0f22" }, "device_types" : [ "open::rcs" ], "notification" : { "open::rcs" : { "template": { "template_id" : "09641749-f288-46e6-8dc6-fae592e8c092" } } } } ``` *Example templated Create and Send a message* ```json { "audience": { "create_and_send": [ { "ua_address": "some-person@example.com", "ua_commercial_opted_in": "2023-04-01T18:45:30", "ua_open_tracking_opted_in": "2023-04-01T18:45:30", "name": "Some Person, Esq.", "totalPurchases": "$ 239.85", "items": [ { "text": "New Line Sneakers", "image": "https://marketing-image-production.example.com/uploads/newlinesneakers.png", "price": "$ 79.95" }, { "text": "Old Line Sneakers", "image": "https://marketing-image-production.example.com/uploads/oldlinesneakers.png", "price": "$ 79.95" }, { "text": "Blue Line Sneakers", "image": "https://marketing-image-production.example.com/uploads/bluelinesneakers.png", "price": "$ 79.95" } ], "receipt": true, "onlineAccount": { "username": "coolUser", "email_receipt": true, "email": "someone@example.com" }, "userAddress": { "address01": "1234 Fake St.", "address02": "Apt. 123", "city": "Place", "state": "CO", "zip": "80202" }, "num_of_purchases": 4 }, { "ua_address": "some-other-person@example.com", "ua_commercial_opted_in": "2023-04-01T18:45:30", "ua_click_tracking_opted_in": "2023-04-01T18:45:30", "name": "The Honorable Some Other Person" } ] }, "device_types": [ "email" ], "notification": { "email": { "template": { "fields": { "subject": "Hi there, {{name}}", "plaintext_body": "Your \n{{#each items}} {{this.text}} {{this.price}} {{/each}}\n are on the way{{#with userAddress}} to {{address01}}{{/with}}!" } }, "sender_name": "Ultimate Sender", "message_type": "transactional", "sender_address": "no-reply@valid-sender-example.com", "reply_to": "no-reply@valid-sender-example.com" } } } ``` *Example CSV audience with nested keys* ```text/csv ua_address,ua_commercial_opted_in,name,address.city,address.state,items.[0].name,items.[0].code,items.[1].name,items.[1].code someone@example.com,2023-04-01T18:45:30,Joe Someone,Portland,OR,Rubber Gloves,abaccgdsagsde,Bleach Alternative,cacadgdesgaga else@example.com,2023-04-21T16:13:01,Sir Else,Seattle,WA,Flashlight,zxcvxcbzxcbza,Shovel,aldfkghalsdkg ``` *Equivalent JSON audience definition* ```json { "audience": { "create_and_send" : [ { "ua_address" : "someone@example.com", "ua_commercial_opted_in" : "2023-04-01T18:45:30", "name" : "Joe Someone", "address" : { "city" : "Portland", "state" : "OR" }, "items" : [ { "name" : "Rubber Gloves", "code" : "abaccgdsagsde" }, { "name" : "Bleach Alternative", "code" : "cacadgdesgaga" } ] }, { "ua_address" : "else@example.com", "ua_commercial_opted_in" : "2023-04-21T16:13:01", "name" : "Sir Else", "address" : { "city" : "Seattle", "state" : "WA" }, "items" : [ { "name" : "Flashlight", "code" : "zxcvxcbzxcbza" }, { "name" : "Shovel", "code" : "aldfkghalsdkg" } ] } ] } } ``` --- # Channels > Schemas for channel management, including channel objects, registration, updates, and channel associations. ## Channel listing object {#channellistingobject} Describes a channel listing object. [Jump to examples ↓](#channellistingobject-examples) - **`address`** `string` The address to send push notifications to when `device_type` is `email` or `open`. For all other `device_type` values, this key is replaced with `push_address`. Example: `email@example.com` - **`alias`** `string` **DEPRECATED** Displays the alias associated with the channel, if one exists. Aliases are the precursor to Named Users, our user mapping system. If you are using aliases, please upgrade to Named Users. Listed as `null` when not set. Example: `alias_nope` Nullable: true - **`attributes`** `object` <[Custom and predefined Attributes]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#attributes)> A dictionary of attributes that you've associated with the channel. See the [Attributes guide](/docs/guides/audience/attributes) for more information about creating and assigning attributes. The attributes listed here are "predefined" by Airship, but you can create new attributes in the Airship dashboard. Attributes associated with a channel or Named User. This object contains predefined attributes that you enable and assign to the channel, or custom attributes that you create and assign. This object enumerates predefined attributes, but you can [create your own in the Airship dashboard](/docs/guides/audience/attributes/adding/). - **`background`** `boolean` If true, the device can receive background push notifications. If false, it cannot. This field only appears for iOS devices. - **`channel_id`** `string` The unique channel identifier for a device. Format: `uuid` Example: `9c36e8c7-5a73-47c0-9716-99fd3d4197d5` - **`commercial_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive commercial emails. Format: `date-time` - **`commercial_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user explicitly denied permission to receive commercial emails. Format: `date-time` - **`created`** `string` The creation [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) of this channel. Format: `date-time` Read only: true - **`device_attributes`** `object` <[Device Attributes]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#device_attributes)> Native attribute properties that Airship gathers automatically assigns to a channel. Varies by channel type. See: [Default Attributes](/docs/reference/data-collection/attributes/#default-attributes). For segmentation, when using `ua_app_version`, `ua_sdk_version`, or `ua_device_os`, only semantic versioning formatting is accepted, and anything after the third decimal place is excluded, e.g., `12.2.3-alpha` is compared as `12.2.3`. You can use operators `equals`, `contains`, `less`, `greater`, `is_empty` with values in the formats `1`, `1.2`, `1.2.3`. - **`device_type`** `string` Specifies the device platform for a channel. Possible values: `ios`, `android`, `amazon`, `web`, `open`, `email`, `sms` - **`email_address`** `string` The email address associated with the email channel when `device_type` is `email`. Example: `name@example.com` - **`installed`** `boolean` If true, the channel is installed. If false, it is uninstalled. - **`ios`** `object` <[iOS channel object]({{< ref "/developer/rest-api/ua/schemas/channels/" >}}#ioschannelobject)> Contains parameters that apply when the `device_type` is set to `ios`. - **`last_registration`** `string` The last registration [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) of this channel, if known. Format: `date-time` Nullable: true Read only: true - **`msisdn`** `string` The phone number associated with the SMS channel. Must be numeric characters only, without leading zeros. Max length: 15 Example: `15035556789` - **`named_user_id`** `string` A customer-chosen ID that represents the device user, e.g., CRM ID. This ID cannot have leading or trailing whitespace. Listed as `null` when not set. Min length: 1, Max length: 128 Example: `john_doe` Nullable: true - **`open`** `object` <[Open channel options]({{< ref "/developer/rest-api/ua/schemas/channels/" >}}#openchanneloptionsobject)> Contains options that apply when the `device_type` is set to `open`. - **`opt_in`** `boolean` If true, the channel is opted in to push notifications. If false, it is not. Required for all types except email. - **`opt_in_date`** `string` `(SMS only)` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the SMS channel gave permission to receive messages. Format: `date-time` Example: `2022-07-07T03:23:13` - **`opt_out_date`** `string` `(SMS only)` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when the SMS channel opted out of receiving messages. Format: `date-time` Example: `2022-07-08T03:23:13` - **`push_address`** `string` Required if `opt_in` is true. The address to send push notifications to for all `device_type` values other than `email` and `open`. When `device_type` is `email` or `open`, this key is replaced with `address`. Example: `FE66489F304DC75B8D6E8200DFF8A456E8DAEACEC428B427E9518741C92C6660` Nullable: true - **`subscription_lists`** `array` <[Subscription List object]({{< ref "/developer/rest-api/ua/schemas/subscription-lists/" >}}#subscriptionlistobject)> Lists all the subscription lists that this channel is subscribed to. - **`suppression_state`** `string` If an email channel is suppressed, the reason for its suppression. Email channels with any suppression state set will not have any delivery to them fulfilled. If a more specific reason is not known, use `imported`. Possible values: `spam_complaint`, `commercial_spam_complaint`, `bounce`, `imported` - **`tag_groups`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> One or more tag group objects (including [Device Property Tags](/docs/reference/device-property-tags/)) associated with this channel. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`tags`** `array[string]` An array of tags associated with this channel. Min items: 0, Max items: 1000 Example: `Federer fan,Messi fan` - **`transactional_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive transactional emails. Users do not need to opt-in to receive transactional emails unless they have previously opted out. Format: `date-time` - **`transactional_opted_out`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user explicitly denied permission to receive transactional emails. Format: `date-time` - **`web`** `object` Contains parameters that apply when the `device_type` is set to `web`. **OBJECT PROPERTIES** - **`subscription`** `object` The web subscription. This optional field is not present for cases where a browser is registered (for purposes of Feature Flags) but isn't opted-in to push notifications. **OBJECT PROPERTIES** - **`keys`** `object` Encryption keys required for signing the push package. **OBJECT PROPERTIES** - **`auth`** `string` The authentication secret. - **`p256dh`** `string` The public key. - **`user_agent_string`** `string` The full user agent string. **Used in:** - [Channel listing]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannels) - [Channel lookup]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannel) - [Look up an email address]({{< ref "/developer/rest-api/ua/operations/email/" >}}#getemailchannel) - [Named User listing or lookup]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#getnameduser) - [SMS channel lookup]({{< ref "/developer/rest-api/ua/operations/sms/" >}}#getsmschannel) **Examples** *Example iOS channel* ```json { "channel_id": "b8f9b663-0a3b-cf45-587a-be880946e881", "device_type": "ios", "installed": true, "background": true, "opt_in": false, "push_address": "FE66489F304DC75B8D6E8200DFF8A456E8DAEACEC428B427E9518741C92C6660", "created": "2020-08-08T20:41:06", "last_registration": "2020-05-01T18:00:27", "named_user_id": "some_id_that_maps_to_your_systems", "alias": null, "tags": [ "tag1", "tag2" ], "tag_groups": { "sports fan": ["Federer fan", "Messi fan"], "music fan": [ "Beyonce", "Muse" ], "ua_locale_country": [ "US" ], "ua_locale_language": [ "en" ] }, "ios": { "badge": 0, "quiettime": { "start": null, "end": null }, "tz": "America/Los_Angeles" } } ``` --- ## Email channel associated by Contact {#emailchannelassociatedbycontactobject} An email channel associated with a Contact. [Jump to examples ↓](#emailchannelassociatedbycontactobject-examples) - **`channel_id`** `string` The unique identifier. Format: `uuid` - **`commercial_opted_in`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when a user gave explicit permission to receive commercial emails. Format: `date-time` - **`email_address`** `string` The email address corresponding to the channel. - **`type`** `string` The channel type. Possible values: `email` **Examples** *Example* ```json { "type": "email", "channel_id": "463c4643-a16c-48da-9585-f2c5406f828b", "email_address": "d*******r@example.com", "commercial_opted_in": "2024-02-11T00:00:00" } ``` --- ## iOS channel object {#ioschannelobject} Contains parameters that apply when the `device_type` is set to `ios`. - **`badge`** `integer` The iOS badge number. Must be greater than zero. Format: `int32` - **`quiettime`** `object` Quiet time settings. Requires presence of `tz`. **OBJECT PROPERTIES** - **`end`** `string` Quiet time end in `HH:MM` format. Example: `07:30` Nullable: true - **`start`** `string` Quiet time start in `HH:MM` format. Example: `21:30` Nullable: true - **`scheduled_summary`** `boolean` If true, the scheduled summary notification status is enabled. - **`time_sensitive`** `boolean` If true, the time sensitive notification status is enabled. - **`tz`** `string` The channel's time zone. A list of possible time zone values is maintained at the [IANA Time Zone Database](http://www.iana.org/time-zones). Example: `America/Los_Angeles` Nullable: true **Used in:** - [Channel listing]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannels) - [Channel lookup]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannel) - [Look up an email address]({{< ref "/developer/rest-api/ua/operations/email/" >}}#getemailchannel) - [Named User listing or lookup]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#getnameduser) - [SMS channel lookup]({{< ref "/developer/rest-api/ua/operations/sms/" >}}#getsmschannel) --- ## Open channel options {#openchanneloptionsobject} Contains options that apply when the `device_type` is set to `open`. - **`identifiers`** `object` A set of up to 100 key:value pairs representing identifiers for this channel in your own delivery systems and delivered as a part of webhook payloads. Example: `[object Object]` - **`old_address`** `string` If a channel exists for the value of `old_address`, replaces that channel's address with the value of `address`. Use infrequently, such as when an end user's phone number or email address permanently changes. - **`open_platform_name`** `string` **REQUIRED** The name of the open channel that this `channel_id` is registered on. Example: `Slack` **Used in:** - [Channel listing]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannels) - [Channel lookup]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#getchannel) - [Look up an email address]({{< ref "/developer/rest-api/ua/operations/email/" >}}#getemailchannel) - [Named User listing or lookup]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#getnameduser) - [SMS channel lookup]({{< ref "/developer/rest-api/ua/operations/sms/" >}}#getsmschannel) --- ## SMS channel associated by Contact {#smschannelassociatedbycontactobject} An SMS channel associated with a Contact. [Jump to examples ↓](#smschannelassociatedbycontactobject-examples) - **`channel_id`** `string` The unique identifier. Format: `uuid` - **`msisdn`** `string` The phone number corresponding to the channel. - **`opt_in`** `boolean` If true, the channel is opted in to push notifications. If false, it is not. - **`sender`** `string` The sender corresponding to the channel. - **`type`** `string` The channel type. Possible values: `sms` **Examples** *Example* ```json { "type": "sms", "channel_id": "a537ac78-ef4f-4f74-8536-6fd620549186", "sender": "1234", "msisdn": "*******3379", "opt_in": true } ``` --- # Contacts > Schemas for managing Contacts, including batch operations, anonymous contact resolution, and channel contact operations. ## Contacts scoped batch item {#contactsscopedbatchitem} Contains `scope` and `subscription_lists` and/or `tags`. At least one of `subscription_lists` or `tags` must be provided. [Jump to examples ↓](#contactsscopedbatchitem-examples) - **`scope`** `array` <[Scopes]({{< ref "/developer/rest-api/ua/schemas/subscription-lists/" >}}#scopes)> **REQUIRED** - **`subscription_lists`** `object` <[Named User Subscription List object]({{< ref "/developer/rest-api/ua/schemas/subscription-lists/" >}}#namedusersubscriptionlistsobject)> Defines the Subscription List changes. - **`tags`** `array[object]` **Used in:** - [Scoped Contact batch operations]({{< ref "/developer/rest-api/ua/operations/contacts/" >}}#performscopedcontactbatchoperations) **Examples** *Example contacts scoped batch item* ```json { "scope": ["web", "email", "app"], "subscription_lists": { "subscribe": ["subscription_1", "subscription_2"], "unsubscribe": ["subscription_3"] } } ``` --- # Content objects > Schemas for [Content](/developer/rest-api/ua/operations/content/) templates and per-channel `content` payloads. ## App and web content template object {#appandwebtemplatesobject} The app and web push fields for a template. [Jump to examples ↓](#appandwebtemplatesobject-examples) - **`alert`** `string` **REQUIRED** The text that will display in your push notification. - **`icon`** `string` A string representing a URL or an image file included in the application's resources. - **`summary`** `string` Supplemental text displayed with the notification. - **`title`** `string` A heading that appears above the notification text when applicable. **Used in:** - [Create content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#createcontenttemplate) - [Create or update content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplatebyexternalid) - [List content templates]({{< ref "/developer/rest-api/ua/operations/content/" >}}#listcontenttemplates) - [Look up a content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplate) - [Look up a content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplatebyexternalid) - [Update content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplate) **Examples** *Example app and web template object* ```json { "title": "Shoe sale on {{level}} floor!", "alert": "All the shoes are on sale {{name}}!", "summary": "Don't miss out!", "icon": "shoes" } ``` --- ## Content template object {#contenttemplateobject} A reusable template containing fields for a message type. Can be referenced by its UUID or a customer-defined external ID. [Jump to examples ↓](#contenttemplateobject-examples) - **`content`** `object` **REQUIRED** The content of the given type, using the associated model object below. **One of:** - [Email content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#emailtemplatesobject) The email-specific fields for a template. - [SMS content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#smstemplatesobject) The SMS-specific fields for a template. - [Open channel content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#openchanneltemplatesobject) The open channel-specific fields for a template. - [App and web content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#appandwebtemplatesobject) The app and web push fields for a template. - [Message Center content template object]({{< ref "/developer/rest-api/ua/schemas/content-objects/" >}}#messagecentertemplatesobject) The Message Center-specific fields for a template. - **`created_at`** `string` The [date-time](#date-time-format) when this template was created. Format: `date-time` Read only: true - **`description`** `string` The description of the template. - **`external_id`** `string` An optional ID for referencing this template in future API calls. Must be unique within your project. - **`feed_references`** `object` <[Feed references object]({{< ref "/developer/rest-api/ua/schemas/external-data-feeds-references/" >}}#feedreferences)> An object used to indicate that an external data feed should be invoked, the name of the feed to invoke, and the way in which to invoke it. You can only include a feed if you include a `templates` object in the payload or set the `personalization` option to `true`. - **`id`** `string` The unique ID assigned to the template. Used to retrieve or reference the template in other endpoints. Format: `uuid` Read only: true - **`modified_at`** `string` The [date-time](#date-time-format) when this template was last modified. Format: `date-time` Read only: true - **`name`** `string` **REQUIRED** The human-readable name of the template. - **`snippet_references`** `object` <[Snippet references object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#snippetreferences)> An object used to indicate that a set of snippets should be loaded for use in message content. Use the following syntax in your payload: `{{> your_snippet_name }}` to reference the snippet content within a notification or rich message. See [Snippets](/docs/guides/personalization/content/snippets/) to see how to create a snippet in the Airship dashboard. - **`type`** `string` **REQUIRED** The type of message. Possible values: `email`, `sms`, `open`, `app`, `web`, `message_center` **Used in:** - [Create content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#createcontenttemplate) - [Create or update content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplatebyexternalid) - [List content templates]({{< ref "/developer/rest-api/ua/operations/content/" >}}#listcontenttemplates) - [Look up a content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplate) - [Look up a content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplatebyexternalid) - [Update content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplate) **Examples** *Example content template object* ```json { "id": "ef34a8d9-0ad7-491c-86b0-aea74da15161", "external_id": "customer-defined-id", "name": "Welcome Message", "description": "Our welcome message", "type": "email", "content": { "subject": "Welcome!", "html_body": "Hi, {{first_name}}! {{>copyright}}", "plaintext_body": "Hi, {{first_name}}!" }, "created_at": "2020-08-17T11:10:02Z", "modified_at": "2020-08-17T11:10:02Z", "feed_references": { "feeds": [ { "name": "featured_product" } ], "defaults": { "featured_product": { "category": "featured" } } }, "snippet_references": { "snippets": [ { "name": "copyright" } ] } } ``` --- ## Email content template object {#emailtemplatesobject} The email-specific fields for a template. [Jump to examples ↓](#emailtemplatesobject-examples) - **`html_body`** `string` **REQUIRED** The HTML content of the email. - **`plaintext_body`** `string` **REQUIRED** The plaintext content of the email. - **`subject`** `string` **REQUIRED** The email subject. **Used in:** - [Create content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#createcontenttemplate) - [Create or update content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplatebyexternalid) - [List content templates]({{< ref "/developer/rest-api/ua/operations/content/" >}}#listcontenttemplates) - [Look up a content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplate) - [Look up a content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplatebyexternalid) - [Update content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplate) **Examples** *Example email template object* ```json { "subject": "Welcome!", "html_body": "Hi, {{first_name}}!", "plaintext_body": "Hi, {{first_name}}!" } ``` --- ## Message Center content template object {#messagecentertemplatesobject} The Message Center-specific fields for a template. [Jump to examples ↓](#messagecentertemplatesobject-examples) - **`html_body`** `string` **REQUIRED** The body of the message. This can be a full HTML message. - **`title`** `string` A heading that appears above the message and in the Message Center inbox. **Used in:** - [Create content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#createcontenttemplate) - [Create or update content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplatebyexternalid) - [List content templates]({{< ref "/developer/rest-api/ua/operations/content/" >}}#listcontenttemplates) - [Look up a content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplate) - [Look up a content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplatebyexternalid) - [Update content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplate) **Examples** *Example Message Center template object* ```json { "html_body": "

Richtext body goes here

Unsubscribe

", "title": "Message Center Notification" } ``` --- ## Open channel content template object {#openchanneltemplatesobject} The open channel-specific fields for a template. [Jump to examples ↓](#openchanneltemplatesobject-examples) - **`alert`** `string` **REQUIRED** The text that will display in your open channel message. - **`media_attachment`** `string` The URL for media you want to include in your message. - **`summary`** `string` Supplemental text displayed with the notification. - **`title`** `string` A heading that appears above the notification text when applicable. **Used in:** - [Create content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#createcontenttemplate) - [Create or update content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplatebyexternalid) - [List content templates]({{< ref "/developer/rest-api/ua/operations/content/" >}}#listcontenttemplates) - [Look up a content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplate) - [Look up a content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplatebyexternalid) - [Update content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplate) **Examples** *Example open channel template object* ```json { "title": "SMS Alert!", "alert": "A shorter alert for SMS users", "summary": "A longer summary of text alongside the notification", "media_attachment": "https://example.com/cat_standing_up.jpeg" } ``` --- ## SMS content template object {#smstemplatesobject} The SMS-specific fields for a template. [Jump to examples ↓](#smstemplatesobject-examples) - **`alert`** `string` **REQUIRED** The SMS content. **Used in:** - [Create content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#createcontenttemplate) - [Create or update content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplatebyexternalid) - [List content templates]({{< ref "/developer/rest-api/ua/operations/content/" >}}#listcontenttemplates) - [Look up a content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplate) - [Look up a content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplatebyexternalid) - [Update content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplate) **Examples** *Example SMS template object* ```json { "alert": "My SMS message" } ``` --- # Create and Send > Objects and samples for [`/create-and-send`](/developer/rest-api/ua/operations/bulk-sending/#createandsend) endpoints. A full object can contain parts of schedule, template, audience, and platform override objects (for `email`, `sms`, or `open::` platforms). The `notification` payload for Create and Send objects supports both stored and inline templates. Using inline templates, you can define and populate variables to personalize notifications to your new channels. {{< note >}} You cannot update channel information or opt-in status using Create and Send. If you want to update channels, refer to the appropriate email, SMS, or open channel endpoints. {{< /note >}} ## Create and Send MMS notification {#mms} The payload for a Create and Send operation that sends a multimedia payload (MMS) to SMS channels. When sending an MMS payload, `device_types` must be set to `mms`. [Jump to examples ↓](#mms-examples) - **`audience`** `object` **REQUIRED** **One of:** - **SMS audience for Create and Send payloads** `object` The SMS information and opt-in parameters for the audience you want to send to. Unknown MSISDNs are registered as new channels. - **`create_and_send`** `array[object]` **REQUIRED** Each object in the array represents an MSISDN you want to send to. Unknown MSISDNs are registered as new channels. Channel registration fields are prefixed with `ua_` and have the same requirements as the [SMS channel registration endpoint](/docs/developer/rest-api/ua/operations/sms/#registersmschannel). All other fields represent variables if `notification` specifies a `template`. Max items: 1000 - - **`bulk_id`** `string` **REQUIRED** A unique string obtained from the [Create bulk send audience operation](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) to target an audience for bulk sending. Format: `uuid` - **`device_types`** `array[string]` **REQUIRED** The platform you want to send notifications to. Possible values: `email`, `mms`, `sms`, `open::` - **`notification`** `object` **REQUIRED** **OBJECT PROPERTIES** - **`mms`** `object` **REQUIRED** A platform override for MMS messages; `device_types` must be set to `mms`. A notification with a platform override that does not match your `device_types` will result in a 400 error. **One of:** - [MMS platform overrides]({{< ref "/developer/rest-api/ua/schemas/platform-overrides/" >}}#mmsoverrideobject) Provides the content for a push to MMS channels. If `sms` is in the `device_type` array, your request may include this object. It cannot be combined with an SMS Platform Override as a single push can only include either an SMS or MMS payload. - [MMS notification with inline template]({{< ref "/developer/rest-api/ua/schemas/platform-overrides-with-templates/" >}}#mmsoverridewithtemplate) Template and notification overrides for a Create and Send payload with `device_types` set to `mms`. With a template, you can provide and populate variables and conditional statements based on those variables. Conditionals begin with `{{#operator}}` and end with `{{/operator}}`. For more information, see [Handlebars](/docs/guides/personalization/handlebars/). **Used in:** - [Create and Send a message]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#createandsend) - [Schedule a Create and Send message]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulecreateandsendoperations) - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) - [Validate Create and Send payload]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#validatecreateandsendpayload) **Examples** *Example Create and Send for MMS without template* ```json { "audience": { "create_and_send": [ { "ua_msisdn": "15558675309", "ua_sender": "15551234567", "ua_opted_in": "2020-11-11T18:45:30", } ] }, "device_types": [ "mms" ], "notification": { "mms": { "fallback_text": "Delivery failed, but you should still check this out.", "subject" : "Hey, thanks for subscribing!", "slides": [ { "text": "Check this out!", "media": { "url": "https://i.example.com/1t466Om.jpg", "content_type": "image/jpeg", "content_length": 52918 } } ] } } } ``` --- ## Create and Send to email channels {#email} The payload for a Create and Send operation to email channels. When sending to email channels, `device_types` must be set to `email`. [Jump to examples ↓](#email-examples) - **`audience`** `object` **REQUIRED** **One of:** - **Email audience for Create and Send payloads** `object` The email addresses and opt-in agreements for the audience you want to send to. Unknown addresses are registered as new channels. - **`create_and_send`** `array[object]` **REQUIRED** Each object in the array represents an email address you want to send to. Unknown addresses are registered as new channels. Channel registration fields are prefixed with `ua_` and have the same requirements as the [email registration endpoint](/docs/developer/rest-api/ua/operations/email/#registeremailchannel). You cannot provide optional channel registration fields using this endpoint (like `locale_language` for email channels). All other fields represent variables if `notification` specifies a `template`. Max items: 1000 - - **`bulk_id`** `string` **REQUIRED** A unique string obtained from the [Create bulk send audience operation](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) to target an audience for bulk sending. Format: `uuid` - **`campaigns`** `object` <[Campaigns object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#campaignsobject)> An object specifying custom campaign categories related to the notification. - **`device_types`** `array[string]` **REQUIRED** The platform you want to send notifications to. Possible values: `email`, `mms`, `sms`, `open::` - **`notification`** `object` **REQUIRED** An `alert` notification or a platform override matching the value in `device types`. A notification with a platform override that does not match your `device_types` will result in a 400 error. **OBJECT PROPERTIES** - **`email`** `object` You can either provide the standard object that you would provide when performing a `/api/push` to an email platform, or you can provide some of the email platform override fields along with an inline template. **One of:** - [Email overrides]({{< ref "/developer/rest-api/ua/schemas/platform-overrides/" >}}#emailoverrideobject) Notification fields specific to email messages. This object is required when `email` is specified in the payload's `device_types` field. - [Email notification with template]({{< ref "/developer/rest-api/ua/schemas/platform-overrides-with-templates/" >}}#emailoverridewithtemplate) Notification fields specific to email messages with an inline template for use in a [Create and Send](/docs/developer/rest-api/ua/operations/bulk-sending/#createandsend) payload. Using a template enables you to provide and populate variables in your notification. You can also add conditional statements based on those variables, determining message text that to send to each member of your audience. Conditionals begin with `{{#operator}}` and end with `{{/operator}}`. For more information, see [Handlebars](/docs/guides/personalization/handlebars/). **Used in:** - [Create and Send a message]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#createandsend) - [Schedule a Create and Send message]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulecreateandsendoperations) - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) - [Validate Create and Send payload]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#validatecreateandsendpayload) **Examples** *Example object* ```json { "audience": { "create_and_send" : [ { "ua_address": "new@example.com", "ua_commercial_opted_in": "2020-11-29T10:34:22" }, { "ua_address" : "ben@example.com", "ua_commercial_opted_out": "2020-11-29T12:45:10" }, { "ua_address" : "mary@example.com", "ua_email_suppression_state": "BOUNCE" } ] }, "device_types" : [ "email" ], "notification" : { "email": { "subject": "Welcome to the Winter Sale! ", "html_body": "

Seasons Greetings

Check out our winter deals!

Unsubscribe

", "plaintext_body": "Greetings! Check out our latest winter deals! [[ua-unsubscribe href=\"http://unsubscribe.urbanairship.com/email/success.html\"]]", "message_type": "transactional", "sender_name": "Airship", "sender_address": "team@airship.com", "reply_to": "no-reply@airship.com", "click_tracking": false, "open_tracking": false, "attachments": [ { "id": "0e10a6b9-725c-4f6b-9af2-9ef5b31328c0", }, { "id": "5503b5fe-ed69-4609-bef6-6fef0e6e428f" } ] } }, "campaigns": { "categories": ["winter sale", "west coast"] } } ``` --- ## Create and Send to open channels {#open} The payload for a Create and Send operation to open channels. When sending to open channels, the `device_type` must be set to `open::`. [Jump to examples ↓](#open-examples) - **`audience`** `object` **REQUIRED** **One of:** - **Open audience for Create and Send payloads** `object` The Open channel addresses and opt-in information for the audience you want to send to. Unknown addresses are registered as new channels. - **`create_and_send`** `array[object]` **REQUIRED** Each object in the array represents an Open channel address you want to send to. Unknown addresses are registered as new channels. Channel registration fields are prefixed with `ua_` and have the same requirements as open channel registration. Max items: 1000 - - **`bulk_id`** `string` **REQUIRED** A unique string obtained from the [Create bulk send audience operation](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) to target an audience for bulk sending. Format: `uuid` - **`campaigns`** `object` <[Campaigns object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#campaignsobject)> An object specifying custom campaign categories related to the notification. - **`device_types`** `array[string]` **REQUIRED** The platform you want to send notifications to. Possible values: `email`, `mms`, `sms`, `open::` - **`notification`** `object` **REQUIRED** An `alert` notification or a platform override matching the value in `device types`. A notification with a platform override that does not match your `device_types` will result in a 400 error. **OBJECT PROPERTIES** - **`open::open_platform_name`** `object` <[Open channel overrides with template]({{< ref "/developer/rest-api/ua/schemas/platform-overrides-with-templates/" >}}#openchanneloverridewithtemplate)> Use a `template` with an open channel-specific message. You can reference a template by ID, or use `{{handlebars}}` directly in your message. **Used in:** - [Create and Send a message]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#createandsend) - [Schedule a Create and Send message]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulecreateandsendoperations) - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) - [Validate Create and Send payload]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#validatecreateandsendpayload) **Examples** *Example object* ```json { "audience" : { "create_and_send": [ { "ua_address" : "36d5a261-0454-40f5-b952-942c4b2b0f22", "name": "Perry" } ] }, "device_types" : [ "open::smart_fridge" ], "notification" : { "open::smart_fridge": { "alert" : "Hey {{name}}, you're out of ice cream!" } }, "campaigns": { "categories": ["needs_ice_cream", "cookies_and_cream"] } } ``` --- ## Create and Send to SMS channels {#sms} The payload for a Create and Send operation to SMS channels. When sending to SMS channels, `device_types` must be set to `sms`. [Jump to examples ↓](#sms-examples) - **`audience`** `object` **REQUIRED** **One of:** - **SMS audience for Create and Send payloads** `object` The SMS information and opt-in parameters for the audience you want to send to. Unknown MSISDNs are registered as new channels. - **`create_and_send`** `array[object]` **REQUIRED** Each object in the array represents an MSISDN you want to send to. Unknown MSISDNs are registered as new channels. Channel registration fields are prefixed with `ua_` and have the same requirements as the [SMS channel registration endpoint](/docs/developer/rest-api/ua/operations/sms/#registersmschannel). All other fields represent variables if `notification` specifies a `template`. Max items: 1000 - - **`bulk_id`** `string` **REQUIRED** A unique string obtained from the [Create bulk send audience operation](/docs/developer/rest-api/ua/operations/bulk-sending/#bulkuploadcreateandsendplatform) to target an audience for bulk sending. Format: `uuid` - **`campaigns`** `object` <[Campaigns object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#campaignsobject)> An object specifying custom campaign categories related to the notification. - **`device_types`** `array[string]` **REQUIRED** The platform you want to send notifications to. Possible values: `email`, `mms`, `sms`, `open::` - **`notification`** `object` **REQUIRED** An `alert` notification or a platform override matching the value in `device types`. A notification with a platform override that does not match your `device_types` will result in a 400 error. **OBJECT PROPERTIES** - **`sms`** `object` **One of:** - [SMS platform overrides]({{< ref "/developer/rest-api/ua/schemas/platform-overrides/" >}}#smsoverrideobject) Provides override options when `sms` is one of the `device_types` specified in the payload. - [SMS notification with template]({{< ref "/developer/rest-api/ua/schemas/platform-overrides-with-templates/" >}}#smsoverridewithtemplate) Notification fields specific to SMS messages with an inline template for use in a [Create and Send](/docs/developer/rest-api/ua/operations/bulk-sending/#createandsend) payload. Using a template enables you to provide and populate variables in your notification. You can also add conditional statements based on those variables, determining message text that to send to each member of your audience. Conditionals begin with `{{#operator}}` and end with `{{/operator}}`. For more information, see [Handlebars](/docs/guides/personalization/handlebars/). **Used in:** - [Create and Send a message]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#createandsend) - [Schedule a Create and Send message]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulecreateandsendoperations) - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) - [Validate Create and Send payload]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#validatecreateandsendpayload) **Examples** *Example object* ```json { "audience": { "create_and_send" : [ { "ua_msisdn": "15558675309", "ua_sender": "12345", "ua_opted_in": "2020-11-11T18:45:30" } ] }, "device_types" : [ "sms" ], "notification" : { "sms": { "alert": "Check out our winter sale! https://www.example.com/amazingly/long/url-that-I-want-to-shorten", "expiry": 172800, "shorten_links": true } }, "campaigns": { "categories": ["winter sale", "west coast"] } } ``` --- # Event segmentation > Event Segmentation lets you target audiences based on lifecycle actions or Custom Events that have occurred. To Segment based on event activity, include an [Activity Object](/developer/rest-api/ua/schemas/event-segmentation/#activityobject) in your audience, and an optional [Where Object](/developer/rest-api/ua/schemas/event-segmentation/#whereobject) to filter on specific event properties. ## Activity audience object {#activityobject} The `activity` object defines the target audience based on lifecycle actions or Custom Event activity, using comparison operators on activity count and recency. Optionally include a `where` object, which filters for specific activity values. In the example to the right, the target audience is users who have opened your app from a notification from the "neowise" campaign at least twice, 3 days ago. [Jump to examples ↓](#activityobject-examples) - **`activity`** `string` **REQUIRED** The target event activity, e.g., `app_open`. Default event values are enumerated below. If you create a custom or predefined event that you wish to segment users on, you must register the event in the Airship dashboard. See [Manage events](/docs/guides/audience/events/manage/). Possible values: `app_open`, `message_received`, `message_center_read`, `message_center_delivered`, `message_center_deleted`, `in_app_message_display`, `in_app_message_resolution`, `in_app_message_expiration`, `screen_view`, `web_session`, `web_click`, `short_link_click`, `first_seen`, `sms_aborted`, `sms_delivered`, `sms_dispatched`, `sms_expired`, `sms_failed`, `sms_rejected`, `sms_undeliverable`, `sms_unknown`, `email_bounce`, `email_click`, `email_delay`, `email_delivered`, `email_injection`, `email_open`, `email_unsubscribe`, `scene_displayed`, `scene_completed`, `scene_incomplete`, `survey_displayed`, `survey_submitted`, `survey_not_submitted` - **`after`** `object` A date value for an absolute comparison or an integer value for a relative comparison. **One of:** - `string` A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format), for example: `"after": "2020-08-01T12:00:00"`. - `integer` - **`before`** `object` A date value for an absolute comparison or an integer value for a relative comparison. **One of:** - `string` A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format), for example: `"before": "2020-08-01T12:00:00"`. - `integer` - **`metric`** `string` The metric you are targeting for the event. When using the metric `count` or `total_value`, `operator` and `value` are required. When using either `first` or `last`, `operator` and `value` are not allowed. Use one of the following combinations instead: * `before`/`precision` * `after`/`precision` * `on`/`on_precision` | Metric | Description | |---|---| | `count` | Evaluate based on the number of event occurrences. | | `total_value` | Evaluate based on the cumulative event `value` associated with the target user. | | `last` | Evaluate based on the last occurrence of an event for a given user/time window. | | `first` | Evaluate based on the first occurrence of an event for a given user/time window. | Possible values: `count`, `total_value`, `last`, `first` - **`on`** `string` Use `on` in conjunction with the `first` or `last` metric to indicate either a specific date or period with precision. Use either: * A date in ISO 8601 format, e.g., `2020-08-10T17:28:34+0000` or * An integer that, when combined with the `on_precision` property, specifies the time period. For example, use `"on": 12` with `"on_precision: "month"` to target events that occurred in December. **One of:** - `string` A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format). - `integer` - **`on_precision`** `string` When using the `first` or `last` metric with the `on` property to target events on. For example, for the 5th of any month, or only in March, use `on_precision`. Possible values: `day`, `month`, `month_day`, `year_month`, `year_month_day` - **`operator`** `string` **REQUIRED** The comparison operator used to evaluate the activity expression. Use these operators (greater/less than, equal to, equal or greater/equal or less) when the `metric` is either `count` or `total_value`. Possible values: `greater`, `less`, `equals`, `greater_eq`, `less_eq` - **`precision`** `string` If using a relative number (integer) for the `before`/`after`/`on` property, the `precision` value will be interpreted as the number of time units ago, e.g., *7 days ago*. Defaults to `days`. Possible values: `days`, `weeks`, `months`, `years` Default: `days` - **`value`** `number` **REQUIRED** The value that the `operator` uses to evaluate the target audience. - **`where`** `object` The [Where Object](/docs/developer/rest-api/ua/schemas/event-segmentation/#whereobject). **Used in:** - [Create experiment (A/B Test)]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#createexperiment) - [Create Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#createsegment) - [Experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiments) - [Experiment lookup]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getexperiment) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Scheduled experiment listing]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#getscheduledexperiments) - [Segment lookup]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#getsegment) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Subscribe or unsubscribe channels to/from subscription lists]({{< ref "/developer/rest-api/ua/operations/channels/" >}}#modifychannelsubscriptions) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Update Segment]({{< ref "/developer/rest-api/ua/operations/segments/" >}}#updatesegment) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) - [Validate experiment]({{< ref "/developer/rest-api/ua/operations/a-b-tests/" >}}#validateexperiment) **Examples** *Activity audience object* ```json { "audience": { "activity": "app_open", "operator": "greater", "value": 2, "after": 3, "precision": "days", "where": { "property": "/_triggering_push/campaigns/categories", "operator": "equals", "value": "neowise" } } } ``` --- ## Where object {#whereobject} `where` is an object that filters on the existence of prior user activity, specified by event properties that you provide. [Jump to examples ↓](#whereobject-examples) - **`compare_as`** `string` Selects the property type for comparison. Possible values: `text`, `number`, `date`, `boolean` - **`operator`** `string` **REQUIRED** The operator in question Possible values: `greater`, `less`, `equals`, `greater_eq`, `less_eq`, `contains`, `present`, `range`, `before`, `after` - **`precision`** `string` Used only for date values. Possible values: `minutes`, `days`, `months`, `years` - **`property`** `string` **REQUIRED** The Custom Event property on which to filter for inclusion in the audience. See [Event Segmentation Properties](/docs/guides/audience/events/events/#events-reference) for properties reference. - **`relative_to`** `string` Used only for date values. Possible values: `future`, `past` - **`value`** `object` **REQUIRED** The value of the property you are filtering for in the `where` object. Use `compare_as` to select the type for comparison. **One of:** - `string` A [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format), e.g., `2020-08-10T17:28:34+0000`. - `number` - `boolean` **Examples** *Example payload to an audience of users who have opened your app as a result of receiving a specific push ID. * ```json { "audience": { "activity": "app_open", "metric": "count", "operator": "greater", "value": 0, "where": { "property": "/_triggering_push/push_id", "operator": "equals", "compare_as": "text", "value": "636abb88-5642-4035-998d-a04c93c499ad" } }, "device_types": [ "ios", "android" ], "notification": { "alert": "Did you get that thing I sent you?" } } ``` --- # External Data Feeds references > A push request property specifying which [External Data Feeds](/guides/personalization/sources/external-data-feeds/) should be invoked and with what parameters in order to support personalization from feed content. {{< important >}} You must first [create an external data feed in the dashboard](/docs/guides/personalization/sources/external-data-feeds/), then you can refer to its ID as the `name` in the feed references object. The Coupons service is a type of external data feed. See [Coupons](/docs/guides/personalization/sources/coupons/) for formatting and usage information. {{< /important >}} ## Feed references object {#feedreferences} An object used to indicate that an external data feed should be invoked, the name of the feed to invoke, and the way in which to invoke it. You can only include a feed if you include a `templates` object in the payload or set the `personalization` option to `true`. [Jump to examples ↓](#feedreferences-examples) - **`defaults`** `object` Default parameter values for your feed. These values override any defaults you set for your feed in the Airship Dashboard. - **`feeds`** `array[object]` **REQUIRED** An array of feeds that you want to use to personalize your message. **Used in:** - [Create content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#createcontenttemplate) - [Create or update content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplatebyexternalid) - [List a specific schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedule) - [List content templates]({{< ref "/developer/rest-api/ua/operations/content/" >}}#listcontenttemplates) - [List schedules]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#getschedules) - [Look up a content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplate) - [Look up a content template by external ID]({{< ref "/developer/rest-api/ua/operations/content/" >}}#getcontenttemplatebyexternalid) - [Schedule a notification]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#schedulenotification) - [Schedule a templated push]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#scheduletemplatedpush) - [Schedule message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#schedulebulksendpush) - [Send a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#sendpush) - [Send message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#bulksendpush) - [Update content template]({{< ref "/developer/rest-api/ua/operations/content/" >}}#updatecontenttemplate) - [Update schedule]({{< ref "/developer/rest-api/ua/operations/schedules/" >}}#updateschedule) - [Validate a push]({{< ref "/developer/rest-api/ua/operations/push/" >}}#validatepush) - [Validate message with bulk ID]({{< ref "/developer/rest-api/ua/operations/bulk-sending/" >}}#validatebulksendpush) **Examples** *Example push external data feeds request* ```http POST /api/push HTTP/1.1 Authorization: Basic Accept: application/vnd.urbanairship+json; version=3 Content-Type: application/json { "device_types": ["ios"], "audience": { "tag": "earlyBirds" }, "notification": { "alert": "{{#feed \"featured_product\"}}Hello, {{user}}, could I interest you in {{product_name}} today?{{/feed}}" }, "options": { "personalization": true }, "feed_references": { "feeds": [ { "name": "featured_product" } ], "defaults": { "featured_product": { "category": "featured" } } } } ``` ```http HTTP/1.1 202 Accepted Content-Type: application/vnd.urbanairship+json; version=3 Content-Length: 123 Data-Attribute: push_ids { "ok": true, "operation_id": "5e7852b0-6909-4e60-a73f-4d6b92d94c80", "push_ids": [ "bf28d158-fefe-475a-9c2a-ed4f69cc891e" ] } ``` *Example feed references object* ```json { "feed_references": { "feeds": [ { "name": "featured_product", "params": { "sub_category": "shoes" }, "on_error": "continue" } ], "defaults": { "featured_product": { "category": "featured" } } } } ``` --- # Named User > A Named User is a proprietary identifier that maps customer-chosen IDs, e.g., CRM data, to Channels. Schemas for managing Named Users, their associations, and updates. ## Named User object {#nameduserresponsebody} The response body for a Named User listing, including tags, channels and attributes associated with the Named User. [Jump to examples ↓](#nameduserresponsebody-examples) - **`attributes`** `object` <[Custom and predefined Attributes]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#attributes)> **REQUIRED** Attributes associated with a channel or Named User. This object contains predefined attributes that you enable and assign to the channel, or custom attributes that you create and assign. This object enumerates predefined attributes, but you can [create your own in the Airship dashboard](/docs/guides/audience/attributes/adding/). - **`channels`** `array` <[Channel listing object]({{< ref "/developer/rest-api/ua/schemas/channels/" >}}#channellistingobject)> **REQUIRED** Listing of channels associated with the Named User. - **`created`** `string` **REQUIRED** The creation [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format). Format: `date-time` - **`last_modified`** `string` **REQUIRED** The last modified [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format). Format: `date-time` - **`named_user_id`** `string` **REQUIRED** A customer-chosen ID that represents a user, e.g., CRM ID. This ID cannot have leading or trailing whitespace. Example: `john_doe` - **`subscription_lists`** `array` <[Subscription List item object]({{< ref "/developer/rest-api/ua/schemas/subscription-lists/" >}}#namedusersubscriptionlistitem)> **REQUIRED** A list of subscription list items associated with the Named User. - **`tags`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> **REQUIRED** One or more tag group objects associated with the Named User. See [Named User Tags](/docs/developer/rest-api/ua/operations/tags/#modifynamedusertags). Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`user_attributes`** `object` **REQUIRED** User attributes consist of three values that are copied from the last channel associated with the Named User. **OBJECT PROPERTIES** - **`ua_country`** `string` An ISO 3166 two-character country code. Example: "US". - **`ua_language`** `string` An ISO 639-1 two-character language code. Example: "en". - **`ua_local_tz`** `string` Time zone as a string. Example: "America/Los_Angeles" **Used in:** - [Named User listing or lookup]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#getnameduser) **Examples** *Example Named User* ```json { "named_user": { "named_user_id": "user-id-1234", "created" : "2020-04-08T20:41:06", "last_modified" : "2020-05-01T18:00:27", "tags": { "loyalty program": [ "silver-member", "ten-plus-years", "valued-customer" ], "crm id": [ "abc-123-def-456" ] }, "subscription_lists": [ { "list_ids": ["example_listId-1", "example_listId-5"], "scope": "web" }, { "list_ids": ["example_listId-2", "example_listId-3"], "scope": "app" }, { "list_ids": ["example_listId-2"], "scope": "web" }, { "list_ids": ["example_listId-3"], "scope": "email" }, { "list_ids": ["example_listId-4"], "scope": "sms" } ], "attributes": { "item_purchased": "Fur removal tool", "cats_name": "Sammy", "pets_age": 12 }, "user_attributes": { "ua_country": "US", "ua_language": "en", "ua_tz": "America/Los_Angeles" }, "channels": [ { "channel_id": "dceafd02-b852-4305-83df-98b65fa40dd4", "device_type": "ios", "installed": true, "opt_in": true, "push_address": "FFFF", "created": "2020-04-08T20:41:06", "last_registration": "2020-05-01T18:00:27", "tags": [ "meow" ] } ] } } ``` --- ## Named User update payload {#nameduserupdate} At least one of `associate`, `disassociate`, `tags`, or `attributes` must be provided. If a channel is provided in both `associate` and `disassociate` sections, a 400 will be returned. - **`associate`** `array` Associate a list of channels or email addresses with the Named User. If the `channel_id` or `email_address` is already associated with the Named User, this operation will do nothing. **Any of:** - **`channel_id`** `string` **REQUIRED** Format: `uuid` Example: `9c36e8c7-5a73-47c0-9716-99fd3d4197d5` - **`device_type`** `string` The device type of the channel. If the channel is not yet registered in Airship and `device_type` is not provided a 400 will be returned. Possible values: `ios`, `android`, `amazon`, `web`, `email`, `sms`, `open` - **`email_address`** `string` **REQUIRED** This email channel must already be registered in Airship or a 400 will be returned Format: `email` Example: `user@example.com` - **`attributes`** `array` <[Attribute assignment]({{< ref "/developer/rest-api/ua/schemas/attributes/" >}}#attributesobject)> Set or remove attributes on a Named User. A single request body may contain `set` or `remove` operations, or both. If both `set` and `remove` fields are present and the intersection of the attributes in these fields is not empty, then a 400 will be returned. If at least one of the attributes included in the request is valid, i.e., at least one attribute exists, Airship returns a 200 with a warning containing a list of attributes that failed to update. - **`disassociate`** `array` Disassociate a channel or an email address from the Named User. **Any of:** - **`channel_id`** `string` **REQUIRED** Format: `uuid` Example: `9c36e8c7-5a73-47c0-9716-99fd3d4197d5` - **`device_type`** `string` The device type of the channel. If the channel is not yet registered in Airship and `device_type` is not provided a 400 will be returned. Possible values: `ios`, `android`, `amazon`, `web`, `email`, `sms`, `open` - **`email_address`** `string` **REQUIRED** This email channel must already be registered in Airship or a 400 will be returned Format: `email` Example: `user@example.com` - **`tags`** `object` Add, remove, or set tags on a Named User. A single request body may contain add and/or remove objects or a single set field. At least one of the add, remove, or set objects must be present in a request. A tag must be < 128 characters. A request with one or more tags longer than 128 characters will return a 400 response. If at least one of the tags included in the request is valid, i.e., at least one tags exists, Airship returns a 200 with a warning containing a list of tags that failed to update. **OBJECT PROPERTIES** - **`add`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Add the list of tags to the Named User, but do not remove any. If the tags are already present, they are not modified. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`remove`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Remove the list of tags from the Named User, but do not remove any others. If the tags are not currently present, nothing happens. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. - **`set`** `object` <[Tag Group object]({{< ref "/developer/rest-api/ua/schemas/tags/" >}}#taggroupobject)> Set these tags for the Named User; any tags previously associated that are not in this current list are removed. Tags belong to Tag Groups. Tag Groups appear within the `tags` object for a Named User or the `tag_groups` object for a channel. See also [Device Properties](/docs/reference/data-collection/device-properties/) ``ua_`` is a reserved prefix for Airship-specific tag groups. A Tag Group has two parts: a "name" string of 1-128 characters, and an array of tags, containing 0-100 tags. Each tag in the array is also a string consisting of 1-128 characters. **Used in:** - [Named User update]({{< ref "/developer/rest-api/ua/operations/named-users/" >}}#updatenameduser) --- # OAuth > Schemas for OAuth token requests, including scopes, assertion JWTs, and subject identifiers. ## Assertion JWT {#assertionjwt} A JSON Web Token (JWT) used for authorization in [OAuth token requests](/docs/developer/rest-api/ua/operations/oauth/#requestoauthtoken). The JWT must be signed with the private key corresponding to the `client_id` in the `kid` header using the ES384 algorithm. **All of:** - **Headers** `object` Assertion JWT headers - **`alg`** `string` **REQUIRED** The signing algorithm. Possible values: `ES384` - **`kid`** `string` **REQUIRED** The key used to sign the JWT, the `client_id`. - **Claims** `object` Assertion JWT claims - **`aud`** `string` **REQUIRED** The valid request endpoint. Example: `https://oauth2.asnapius.com/token` - **`exp`** `integer` **REQUIRED** The `assertion`'s expiration timestamp in seconds since epoch, after which it is not valid. The expiry must not be more than 10 minutes in the future. This is for the `assertion`, not for the token that will be returned. Example: `1681862754` - **`iat`** `integer` **REQUIRED** The issue timestamp in seconds since epoch. Example: `168186250` - **`ipaddr`** `string` A space-delimited list of CIDR representations of valid IP addresses to which the issued token is restricted. - **`iss`** `string` **REQUIRED** The issuer, the `client_id`. - **`nonce`** `string` **REQUIRED** A unique string that must not have been used recently with this `client_id`. We will store this for a minimum of 2 hours. If you are relying on the nonce to defend against replay attacks, it is recommended to also enforce a narrow *ipaddr* range in order to prevent requests that utilize the returned access token from being replayed by an outside client. Min length: 1, Max length: 50 - **`scope`** `string` <[OAuth Scope]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#oauthscope)> A space-delimited list of scopes to which the returned claim should be restricted. If not provided, the full list of scopes the `client_id` is granted will be in the returned claim. The value of the scope parameter is a list of space-delimited, case-sensitive strings. If multiple scopes are specified, their order does not matter. Each string adds an additional access range to the requested scope. For more information about scope values, see [OAuth token scopes](/docs/developer/rest-api/ua/api-auth-reference/#oauth-token-scopes) in the *Airship API Authorization Reference* documentation. * `att`: Attachments * `chn`: Channels * `tpl`: Content * `evt`: Events * `lst`: Lists * `nu`: Named Users * `pln`: Pipelines * `psh`: Push * `sch`: Schedules Possible values: `att`, `chn`, `tpl`, `evt`, `lst`, `nu`, `pln`, `psh`, `sch` - **`sub`** `object` <[Subject]({{< ref "/developer/rest-api/ua/schemas/oauth/" >}}#subject)> **REQUIRED** A space-delimited set of identifiers for which subjects a token is allowed. An `app` subject is required. Example: `app:JQIMcndxIHWy2QISpt1SpZ`. A space-delimited set of identifiers for which subjects a token is allowed. Example: `app:JQIMcndxIHWy2QISpt1SpZ` * `app`: May operate on the given app **Used in:** - [Request token]({{< ref "/developer/rest-api/ua/operations/oauth/" >}}#requestoauthtoken) --- ## OAuth Scope {#oauthscope} The value of the scope parameter is a list of space-delimited, case-sensitive strings. If multiple scopes are specified, their order does not matter. Each string adds an additional access range to the requested scope. For more information about scope values, see [OAuth token scopes](/docs/developer/rest-api/ua/api-auth-reference/#oauth-token-scopes) in the *Airship API Authorization Reference* documentation. * `att`: Attachments * `chn`: Channels * `tpl`: Content * `evt`: Events * `lst`: Lists * `nu`: Named Users * `pln`: Pipelines * `psh`: Push * `sch`: Schedules `string` Allowed values: `att`, `chn`, `tpl`, `evt`, `lst`, `nu`, `pln`, `psh`, `sch` **Used in:** - [Request token]({{< ref "/developer/rest-api/ua/operations/oauth/" >}}#requestoauthtoken) --- ## Subject {#subject} A space-delimited set of identifiers for which subjects a token is allowed. Example: `app:JQIMcndxIHWy2QISpt1SpZ` * `app`: May operate on the given app **Used in:** - [Request token]({{< ref "/developer/rest-api/ua/operations/oauth/" >}}#requestoauthtoken) --- # Personalization template objects > Personalization template objects, including pushes to templates and template listing. ## Push template payload {#pushtemplatepayload} A push template payload defines a push by overriding the variables defined in a specific template object. Specifically, a push template object specifies push audience and device types, along with substitutions for the variables defined in a template. [Jump to examples ↓](#pushtemplatepayload-examples) - **`audience`** `object` <[Audience selector (max 1000)]({{< ref "/developer/rest-api/ua/schemas/audience-selection/" >}}#audienceselector1000)> **REQUIRED** The audience for the template. An audience selector forms the expression that determines the set of channels to target. - **`campaigns`** `object` <[Campaigns object]({{< ref "/developer/rest-api/ua/schemas/push/" >}}#campaignsobject)> An object specifying custom campaign categories related to the notification. - **`device_types`** `array[string]` **REQUIRED** An array containing one or more strings identifying targeted platforms. Min items: 1 Possible values: `android`, `amazon`, `ios`, `web`, `sms`, `mms`, `email`, `open::open_platform_name` - **`merge_data`** `object` **REQUIRED** A template selector describing the template ID and variable substitutions to use with it. **OBJECT PROPERTIES** - **`substitutions`** `object` An object containing overrides for your template's variables. The key-value pairs in this object are the value of the `key` items defined in your template, and the values you want to substitute for the `default_value` of those keys. - **`template_id`** `string` **REQUIRED** Specifies the template to override; corresponds to the `id` in `/templates` responses. Format: `uuid` Example: `ef34a8d9-0ad7-491c-86b0-aea74da15161` **Used in:** - [Push to template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#pushtotemplate) - [Validate a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#validatetemplate) **Examples** *Push template payload example* ```json { "audience": { "tag": [ "yanny", "laurel" ] }, "device_types": [ "email", "ios", "android", "web" ], "merge_data": { "template_id": "8cce6cc8-7d78-43c7-80b5-81ac24c07672", "substitutions": { "FIRST_NAME": "Bob", "LAST_NAME": "Takahashi", "TITLE": null } }, "campaigns": { "categories": [ "winter sale", "west coast" ] } } ``` --- ## Template object {#templateobject} A template object is a skeleton for a push. This is the object used for template creation, and returned by the template listing and lookup endpoints. [Jump to examples ↓](#templateobject-examples) - **`created_at`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when this template was created. Format: `date-time` Read only: true - **`description`** `string` The description for the template. - **`id`** `string` The unique ID assigned to this template. Used to retrieve or use the template in other endpoints. Format: `uuid` Read only: true - **`last_used`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when this template's definition was last used. This attribute cannot template-based specified when the template is created and will only be present when template objects are provided by the template retrieval and template listing endpoints. Format: `date-time` Read only: true - **`modified_at`** `string` The [date-time](/docs/developer/rest-api/ua/introduction/#date-time-format) when this template was last modified. Format: `date-time` Read only: true - **`name`** `string` **REQUIRED** The name of the template. - **`push`** `object` <[Template push object]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#templatepushobject)> A partial push object describing everything about a push notification, except for the `audience` and `device_types` keys (which are defined in the [Push template payload](/docs/developer/rest-api/ua/schemas/personalization-template-objects/#pushtemplatepayload)) and the `message` key (which is incompatible with templates). - **`variables`** `array` <[Template variables]({{< ref "/developer/rest-api/ua/schemas/personalization-template-objects/" >}}#templatevariableobject)> **REQUIRED** An array of variable specifications. Variables can be customized when pushing based on the template. **Used in:** - [Create template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#createtemplate) - [List templates]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#gettemplates) - [Look up a template]({{< ref "/developer/rest-api/ua/operations/personalization/" >}}#gettemplate) **Examples** *Basic template object* ```json { "name": "