Skip to main content
POST
/
templates
cURL
curl --request POST \
  --url https://api.onesignal.com/templates \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: <content-type>' \
  --data '
{
  "app_id": "YOUR_APP_ID",
  "name": "YOUR_TEMPLATE_NAME",
  "isEmail": true,
  "email_subject": "<string>",
  "email_body": "<string>",
  "isSMS": true,
  "dynamic_content": "{\"campaign_id\": {\"A\": {\"title\": \"Custom Title A\", \"message\": \"Custom Message A\", \"url\": \"https://www.onesignal.com\"}, \"B\": {\"title\": \"Custom Title B\", \"message\": \"Custom Message B\", \"url\": \"https://www.onesignal.com/login\"}}}"
}
'
import Onesignal from '@onesignal/node-onesignal';

const configuration = Onesignal.createConfiguration({
restApiKey: 'YOUR_REST_API_KEY',
});
const apiInstance = new Onesignal.DefaultApi(configuration);

// CreateTemplateRequest
const createTemplateRequest: Onesignal.CreateTemplateRequest = {
app_id: "app_id_example",
name: "name_example",
contents: {
en: "en_example",
ar: "ar_example",
bs: "bs_example",
bg: "bg_example",
ca: "ca_example",
zh_hans: "zh_hans_example",
zh_hant: "zh_hant_example",
zh: "zh_example",
hr: "hr_example",
cs: "cs_example",
da: "da_example",
nl: "nl_example",
et: "et_example",
fi: "fi_example",
fr: "fr_example",
ka: "ka_example",
de: "de_example",
el: "el_example",
hi: "hi_example",
he: "he_example",
hu: "hu_example",
id: "id_example",
it: "it_example",
ja: "ja_example",
ko: "ko_example",
lv: "lv_example",
lt: "lt_example",
ms: "ms_example",
nb: "nb_example",
pl: "pl_example",
fa: "fa_example",
pt: "pt_example",
pa: "pa_example",
ro: "ro_example",
ru: "ru_example",
sr: "sr_example",
sk: "sk_example",
es: "es_example",
sv: "sv_example",
th: "th_example",
tr: "tr_example",
uk: "uk_example",
vi: "vi_example",
},
headings: {
en: "en_example",
ar: "ar_example",
bs: "bs_example",
bg: "bg_example",
ca: "ca_example",
zh_hans: "zh_hans_example",
zh_hant: "zh_hant_example",
zh: "zh_example",
hr: "hr_example",
cs: "cs_example",
da: "da_example",
nl: "nl_example",
et: "et_example",
fi: "fi_example",
fr: "fr_example",
ka: "ka_example",
de: "de_example",
el: "el_example",
hi: "hi_example",
he: "he_example",
hu: "hu_example",
id: "id_example",
it: "it_example",
ja: "ja_example",
ko: "ko_example",
lv: "lv_example",
lt: "lt_example",
ms: "ms_example",
nb: "nb_example",
pl: "pl_example",
fa: "fa_example",
pt: "pt_example",
pa: "pa_example",
ro: "ro_example",
ru: "ru_example",
sr: "sr_example",
sk: "sk_example",
es: "es_example",
sv: "sv_example",
th: "th_example",
tr: "tr_example",
uk: "uk_example",
vi: "vi_example",
},
subtitle: {
en: "en_example",
ar: "ar_example",
bs: "bs_example",
bg: "bg_example",
ca: "ca_example",
zh_hans: "zh_hans_example",
zh_hant: "zh_hant_example",
zh: "zh_example",
hr: "hr_example",
cs: "cs_example",
da: "da_example",
nl: "nl_example",
et: "et_example",
fi: "fi_example",
fr: "fr_example",
ka: "ka_example",
de: "de_example",
el: "el_example",
hi: "hi_example",
he: "he_example",
hu: "hu_example",
id: "id_example",
it: "it_example",
ja: "ja_example",
ko: "ko_example",
lv: "lv_example",
lt: "lt_example",
ms: "ms_example",
nb: "nb_example",
pl: "pl_example",
fa: "fa_example",
pt: "pt_example",
pa: "pa_example",
ro: "ro_example",
ru: "ru_example",
sr: "sr_example",
sk: "sk_example",
es: "es_example",
sv: "sv_example",
th: "th_example",
tr: "tr_example",
uk: "uk_example",
vi: "vi_example",
},
is_email: true,
email_subject: "email_subject_example",
email_body: "email_body_example",
email_bcc: [
"email_bcc_example",
],
is_sms: true,
dynamic_content: "dynamic_content_example",
};

try {
const response = await apiInstance.createTemplate(createTemplateRequest);
console.log(response);
} catch (e) {
if (e instanceof Onesignal.ApiException) {
// `e.errorMessages` flattens any error-envelope shape to a `string[]`;
// the raw parsed body remains on `e.body`.
console.error("createTemplate failed: HTTP " + e.code, e.errorMessages);
} else {
throw e;
}
}
import onesignal
from onesignal.api import default_api
from onesignal.models import *
from pprint import pprint

# See configuration.py for a list of all supported configuration parameters.
# Some of the OneSignal endpoints require ORGANIZATION_API_KEY token for authorization, while others require REST_API_KEY.
# We recommend adding both of them in the configuration page so that you will not need to figure it out yourself.
configuration = onesignal.Configuration(
rest_api_key = "YOUR_REST_API_KEY", # App REST API key required for most endpoints
organization_api_key = "YOUR_ORGANIZATION_API_KEY" # Organization key is only required for creating new apps and other top-level endpoints
)


# Enter a context with an instance of the API client
with onesignal.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = default_api.DefaultApi(api_client)
create_template_request = CreateTemplateRequest(
app_id="app_id_example",
name="name_example",
contents=LanguageStringMap(
en="en_example",
ar="ar_example",
bs="bs_example",
bg="bg_example",
ca="ca_example",
zh_hans="zh_hans_example",
zh_hant="zh_hant_example",
zh="zh_example",
hr="hr_example",
cs="cs_example",
da="da_example",
nl="nl_example",
et="et_example",
fi="fi_example",
fr="fr_example",
ka="ka_example",
de="de_example",
el="el_example",
hi="hi_example",
he="he_example",
hu="hu_example",
id="id_example",
it="it_example",
ja="ja_example",
ko="ko_example",
lv="lv_example",
lt="lt_example",
ms="ms_example",
nb="nb_example",
pl="pl_example",
fa="fa_example",
pt="pt_example",
pa="pa_example",
ro="ro_example",
ru="ru_example",
sr="sr_example",
sk="sk_example",
es="es_example",
sv="sv_example",
th="th_example",
tr="tr_example",
uk="uk_example",
vi="vi_example",
),
headings=LanguageStringMap(
en="en_example",
ar="ar_example",
bs="bs_example",
bg="bg_example",
ca="ca_example",
zh_hans="zh_hans_example",
zh_hant="zh_hant_example",
zh="zh_example",
hr="hr_example",
cs="cs_example",
da="da_example",
nl="nl_example",
et="et_example",
fi="fi_example",
fr="fr_example",
ka="ka_example",
de="de_example",
el="el_example",
hi="hi_example",
he="he_example",
hu="hu_example",
id="id_example",
it="it_example",
ja="ja_example",
ko="ko_example",
lv="lv_example",
lt="lt_example",
ms="ms_example",
nb="nb_example",
pl="pl_example",
fa="fa_example",
pt="pt_example",
pa="pa_example",
ro="ro_example",
ru="ru_example",
sr="sr_example",
sk="sk_example",
es="es_example",
sv="sv_example",
th="th_example",
tr="tr_example",
uk="uk_example",
vi="vi_example",
),
subtitle=LanguageStringMap(
en="en_example",
ar="ar_example",
bs="bs_example",
bg="bg_example",
ca="ca_example",
zh_hans="zh_hans_example",
zh_hant="zh_hant_example",
zh="zh_example",
hr="hr_example",
cs="cs_example",
da="da_example",
nl="nl_example",
et="et_example",
fi="fi_example",
fr="fr_example",
ka="ka_example",
de="de_example",
el="el_example",
hi="hi_example",
he="he_example",
hu="hu_example",
id="id_example",
it="it_example",
ja="ja_example",
ko="ko_example",
lv="lv_example",
lt="lt_example",
ms="ms_example",
nb="nb_example",
pl="pl_example",
fa="fa_example",
pt="pt_example",
pa="pa_example",
ro="ro_example",
ru="ru_example",
sr="sr_example",
sk="sk_example",
es="es_example",
sv="sv_example",
th="th_example",
tr="tr_example",
uk="uk_example",
vi="vi_example",
),
is_email=True,
email_subject="email_subject_example",
email_body="email_body_example",
email_bcc=[
"email_bcc_example",
],
is_sms=True,
dynamic_content="dynamic_content_example",
)

try:
# Create template
api_response = api_instance.create_template(create_template_request)
pprint(api_response)
except onesignal.ApiException as e:
print("Exception when calling DefaultApi->create_template: %s\n" % e)
print("Status Code: %s" % e.status)
print("Response Body: %s" % e.body)
<?php
require_once(__DIR__ . '/vendor/autoload.php');


// Configure Bearer authorization: rest_api_key
$config = onesignal\client\Configuration::getDefaultConfiguration()
->setRestApiKeyToken('YOUR_REST_API_KEY')
->setOrganizationApiKeyToken('YOUR_ORGANIZATION_API_KEY');



$apiInstance = new onesignal\client\Api\DefaultApi(
// If you want use custom http client, pass your client which implements `GuzzleHttp\ClientInterface`.
// This is optional, `GuzzleHttp\Client` will be used as default.
new GuzzleHttp\Client(),
$config
);
$create_template_request = new \onesignal\client\model\CreateTemplateRequest(); // \onesignal\client\model\CreateTemplateRequest

try {
$result = $apiInstance->createTemplate($create_template_request);
print_r($result);
} catch (\onesignal\client\ApiException $e) {
echo 'Exception when calling DefaultApi->createTemplate: ', $e->getMessage(), PHP_EOL;
echo 'Status Code: ', $e->getCode(), PHP_EOL;
// getErrorMessages() flattens any error-envelope shape to a string[];
// the raw body remains on getResponseBody().
echo 'Error Messages: ', implode(', ', $e->getErrorMessages()), PHP_EOL;
echo 'Response Body: ', $e->getResponseBody(), PHP_EOL;
} catch (\Exception $e) {
echo 'Exception when calling DefaultApi->createTemplate: ', $e->getMessage(), PHP_EOL;
}
package main

import (
"context"
"fmt"
"os"

"github.com/OneSignal/onesignal-go-api/v5"
)

func main() {
createTemplateRequest := *onesignal.NewCreateTemplateRequest("AppId_example", "Name_example", *onesignal.NewLanguageStringMap()) // CreateTemplateRequest |

configuration := onesignal.NewConfiguration()
apiClient := onesignal.NewAPIClient(configuration)

restAuth := context.WithValue(context.Background(), onesignal.RestApiKey, "YOUR_REST_API_KEY") // App REST API key required for most endpoints

resp, r, err := apiClient.DefaultApi.CreateTemplate(restAuth).CreateTemplateRequest(createTemplateRequest).Execute()

if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `DefaultApi.CreateTemplate``: %v\n", err)
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
if apiErr, ok := err.(*onesignal.GenericOpenAPIError); ok {
// ErrorMessages() flattens any error-envelope shape to a []string;
// the raw body remains on Body().
fmt.Fprintf(os.Stderr, "Error Messages: %v\n", apiErr.ErrorMessages())
fmt.Fprintf(os.Stderr, "Response Body: %s\n", apiErr.Body())
}
}
// response from `CreateTemplate`: TemplateResource
fmt.Fprintf(os.Stdout, "Response from `DefaultApi.CreateTemplate`: %v\n", resp)
}
require 'onesignal'
# setup authorization
OneSignal.configure do |config|
# Configure Bearer authorization: rest_api_key
config.rest_api_key = 'YOUR_REST_API_KEY'

end

api_instance = OneSignal::DefaultApi.new
create_template_request = OneSignal::CreateTemplateRequest.new({app_id: 'app_id_example', name: 'name_example', contents: OneSignal::LanguageStringMap.new}) # CreateTemplateRequest |

begin
# Create template
result = api_instance.create_template(create_template_request)
p result
rescue OneSignal::ApiError => e
puts "Error when calling DefaultApi->create_template: #{e}"
puts "Status Code: #{e.code}"
# `e.error_messages` flattens any error-envelope shape to an Array<String>;
# the raw body remains on `e.response_body`.
puts "Error Messages: #{e.error_messages}"
puts "Response Body: #{e.response_body}"
end
// Import classes:
import com.onesignal.client.ApiClient;
import com.onesignal.client.ApiException;
import com.onesignal.client.Configuration;
import com.onesignal.client.auth.*;
import com.onesignal.client.model.*;
import com.onesignal.client.api.DefaultApi;

public class Example {
public static void main(String[] args) {
ApiClient defaultClient = Configuration.getDefaultApiClient();
defaultClient.setBasePath("https://api.onesignal.com");

// Configure HTTP bearer authorization: rest_api_key
HttpBearerAuth rest_api_key = (HttpBearerAuth) defaultClient.getAuthentication("rest_api_key");
rest_api_key.setBearerToken("YOUR_REST_API_KEY");

DefaultApi apiInstance = new DefaultApi(defaultClient);
CreateTemplateRequest createTemplateRequest = new CreateTemplateRequest(); // CreateTemplateRequest |
try {
TemplateResource result = apiInstance.createTemplate(createTemplateRequest);
System.out.println(result);
} catch (ApiException e) {
System.err.println("Exception when calling DefaultApi#createTemplate");
System.err.println("Status code: " + e.getCode());
// getErrorMessages() flattens any error-envelope shape to a List<String>;
// the raw body remains on getResponseBody().
System.err.println("Error messages: " + e.getErrorMessages());
System.err.println("Reason: " + e.getResponseBody());
System.err.println("Response headers: " + e.getResponseHeaders());
e.printStackTrace();
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using OneSignalApi.Api;
using OneSignalApi.Client;
using OneSignalApi.Model;

namespace Example
{
public class CreateTemplateExample
{
public static void Main()
{
Configuration config = new Configuration();
config.BasePath = "https://api.onesignal.com";
// Configure Bearer token for authorization: rest_api_key
config.AccessToken = "YOUR_REST_API_KEY";

var apiInstance = new DefaultApi(config);
var createTemplateRequest = new CreateTemplateRequest(); // CreateTemplateRequest |

try
{
// Create template
TemplateResource result = apiInstance.CreateTemplate(createTemplateRequest);
Debug.WriteLine(result);
}
catch (ApiException e)
{
Debug.Print("Exception when calling DefaultApi.CreateTemplate: " + e.Message );
Debug.Print("Status Code: "+ e.ErrorCode);
// e.ErrorMessages flattens any error-envelope shape to an IReadOnlyList<string>;
// the raw body remains on e.ErrorContent.
Debug.Print("Error Messages: " + string.Join(", ", e.ErrorMessages));
Debug.Print("Response Body: " + e.ErrorContent);
Debug.Print(e.StackTrace);
}
}
}
}
use onesignal_rust_api::apis::configuration::Configuration;
use onesignal_rust_api::apis::default_api;

use onesignal_rust_api::models;


#[tokio::main]
async fn main() {
let mut configuration = Configuration::new();
configuration.rest_api_key_token = Some("YOUR_REST_API_KEY".to_string());


// Realistic values are pulled from the spec's `example:` fields where present.
let create_template_request: models::CreateTemplateRequest = todo!();

match default_api::create_template(&configuration, create_template_request).await {
Ok(resp) => println!("{:?}", resp),
Err(e @ onesignal_rust_api::apis::Error::ResponseError(_)) => {
// `e.error_messages()` flattens any error-envelope shape to a Vec<String>;
// the raw response remains on the ResponseError variant.
eprintln!("create_template failed: {:?}", e.error_messages());
}
Err(e) => eprintln!("create_template failed: {:?}", e),
}
}
"{\n  \"id\": \"b17ebe45-ae35-4dce-11f8-8c3b3894a432\",\n  \"name\": \"new template created via the API\",\n  \"created_at\": \"2023-08-02T18:09:02Z\",\n  \"updated_at\": \"2023-08-02T18:09:02Z\",\n  \"content\": {\n    \"isAndroid\": true,\n    \"isIos\": true,\n    \"isMacOSX\": true,\n    \"isAdm\": true,\n    \"isAlexa\": null,\n    \"isWP\": true,\n    \"isWP_WNS\": true,\n    \"isChrome\": true,\n    \"isChromeWeb\": true,\n    \"isSafari\": true,\n    \"isFirefox\": true,\n    \"isEdge\": true,\n    \"headings\": {\n      \"en\": \"hello from the api!\"\n    },\n    \"subtitle\": null,\n    \"contents\": {\n      \"en\": \"why hello there!\"\n    },\n    \"global_image\": null,\n    \"url\": \"https://example.com\",\n    \"isEmail\": null,\n    \"email_body\": null,\n    \"email_subject\": null,\n    \"email_preheader\": null,\n    \"isSMS\": null,\n    \"sms_from\": null,\n    \"sms_media_urls\": null,\n    \"email_reply_to_address\": null,\n    \"disable_email_click_tracking\": null\n  }\n}"
"// returned if isEmail:true, but there is no email body content available in the request.\n{\n    \"success\": false,\n    \"errors\": [\n        \"'message' Email body can not be blank\"\n    ]\n}"
"<!-- returned when the request does not contain any contents available to be saved in the template -->\n<!-- can also be returned if creating a push template without setting the value as an object -->\n<title>The change you wanted was rejected (422)</title>"
{
"errors": [
"API rate limit exceeded"
]
}
{
"errors": [
"Service temporarily unavailable"
]
}

Overview

Use this endpoint to create a new message template in your OneSignal app. Once created, the template becomes available for use when sending messages via both the Dashboard and the REST API by referencing the template_id. Templates streamline and standardize message content across push, email, and SMS channels.
See Templates for more information.

How to use this API

Before using this endpoint, ensure that the target channel (push, email, or SMS) is properly configured in your OneSignal app. See Channel Setup for guidance.

Push Templates

Requirements:
  • Set the contents property with the English (en) language key.
  • All Push Channel Properties are valid for use in push templates.
  • By default, all push platforms are enabled. You can target specific platforms by explicitly setting them (e.g., isAndroid: true disables others).

Email Templates

Requirements:
  • Set isEmail: true.
  • Include both email_subject and email_body.
  • All Email Channel Properties are valid for use in email templates.

SMS Templates

Requirements:
  • Set isSMS: true.
  • Provide SMS-specific parameters like contents.
  • All SMS Channel Properties are valid for use in SMS templates.

Headers

Authorization
string
default:Key YOUR_APP_API_KEY
required

Your App API key with prefix Key. See Keys & IDs.

Content-Type
string
default:application/json; charset=utf-8
required

Body

application/json
app_id
string
default:YOUR_APP_ID
required

Your OneSignal App ID in UUID v4 format. See Keys & IDs.

name
string
default:YOUR_TEMPLATE_NAME
required

An internal name you set to help organize and track Templates. Maximum 128 characters.

contents
object

The main message body with language-specific values. Required for push and SMS templates. Supports Message Personalization.

isEmail
boolean

Required to be set true for email templates.

email_subject
string

Required for email templates. The subject of the email. Supports Message Personalization.

email_body
string

The body of the email in HTML format. Required for email templates. Supports Message Personalization.

isSMS
boolean

Required to be set true for SMS templates.

dynamic_content
object

Add personalization to your templates programmatically. No need to upload a CSV. See Dynamic Content for details.

Example:

"{\"campaign_id\": {\"A\": {\"title\": \"Custom Title A\", \"message\": \"Custom Message A\", \"url\": \"https://www.onesignal.com\"}, \"B\": {\"title\": \"Custom Title B\", \"message\": \"Custom Message B\", \"url\": \"https://www.onesignal.com/login\"}}}"

Response

The created template record. content reflects the configuration as stored — fields not relevant to the chosen channel are returned as null.

A template record. The content block is a TemplateResourceContent whose populated fields depend on the template's channel(s).

id
string<uuid>
required

Template ID in UUID v4 format.

name
string

Internal label set when the template was created or last updated. Maximum 128 characters.

channel
enum<string>

The primary channel the template is configured for. Note: SMS is uppercased while the others are lowercased.

Available options:
push,
email,
SMS
created_at
string<date-time>

ISO-8601 timestamp when the template was created.

updated_at
string<date-time>

ISO-8601 timestamp when the template was last updated.

content
object

The content block of a template. Every field is nullable: a field is populated only when the corresponding channel feature is enabled for the template. For example, push fields (isAndroid, isIos, headings, ...) are populated for push templates; email fields (isEmail, email_body, ...) for email templates; and SMS fields (isSMS, sms_from, ...) for SMS templates. Cross-channel templates may have multiple feature blocks populated.