[SalesForce] Creating a Data Extension via SSJS SOAP call

EDIT

The issue was that I have SUBSCRIBER_KEY functionality turned on for my account, so I need to set the SendableSubscriberField to 'Subscriber Key' or the call will fail.


I have been able to utilize similar SSJS code previously and have mimicked some similar questions from SFSE, but everything I try, winds up with me receiving a 405 Error Method Not Allowed.

If anyone can help me find what I am missing/forgetting to do/doing wrong in the below snippet, it would be GREATLY appreciated.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title></title>
   </head>
<body>
<script runat="server"> 

Platform.Load("core", "1");     

    var user = 'User';
    var pass = 'Pass';
    var payload = '';
    var endpoint = 'https://webservice.exacttarget.com/Service.asmx'
    var result;

    // Create SOAP Call

    payload += '<?xml version="1.0" encoding="UTF-8"?>';
    payload += '<Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
    payload += '        <Header>';
    payload += '            <Action mustUnderstand="1">Create</Action>';
    payload += '            <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">';
    payload += '                <UsernameToken>';
    payload += '                    <Username>' + user + '</Username>';
    payload += '                    <Password>' + pass + '</Password>';
    payload += '                </UsernameToken>';
    payload += '            </Security>';
    payload += '         </Header>';
    payload += '        <Body>';
    payload += '            <CreateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI" >';
    payload += '              <Options></Options>';
    payload += '              <Objects xmlns:ns1="http://exacttarget.com/wsdl/partnerAPI" xsi:type="ns1:DataExtension">';
    payload += '                <CustomerKey>CustomerKey</CustomerKey>';
    payload += '                <Name>CustomerKey</Name>';
    payload += '                <IsSendable>true</IsSendable>/';
    payload += '                <SendableDataExtensionField>';
    payload += '                  <CustomerKey>EmailAddress_Key</CustomerKey>';
    payload += '                  <Name>EmailAddress</Name>';
    payload += '                  <FieldType>EmailAddress</FieldType>';
    payload += '                </SendableDataExtensionField>';
    payload += '                <SendableSubscriberField>';
    payload += '                  <Name>Email Address</Name>';
    payload += '                  <Value></Value>';
    payload += '                </SendableSubscriberField>';
    payload += '                <Fields>';
    payload += '                    <Field>';
    payload += '                        <CustomerKey>EmailAddress_Key</CustomerKey>';
    payload += '                        <Name>EmailAddress</Name>';
    payload += '                        <FieldType>EmailAddress</FieldType>';
    payload += '                    </Field>';
    payload += '                    <Field>';
    payload += '                        <CustomerKey>ChannelUser_Key</CustomerKey>';
    payload += '                        <Name>ChannelUser</Name>';
    payload += '                        <FieldType>Text</FieldType>';
    payload += '                    </Field>';
    payload += '                </Fields> ';
    payload += '              </Objects> ';  
    payload += '            </CreateRequest>';
    payload += '       </Body>';
    payload += '</Envelope>';

    try {
        result = HTTP.Post(endpoint, "text/xml", payload, ["SOAPAction"], ["Create"]);
    } catch (e) {
        Write(Stringify(e));
    }

    Write(Stringify(result));

</script>
</body>
</html>

Best Answer

I'm not sure why you would want to make an HTTP.POST call to the SOAP API to achieve this.

If you use the platform API functions available in SSJS (or AMPscript), that will take care of authentication and also resolve the correct Web Service endpoint.

Here's how you would create a Sendable DE using platform API functions in SSJS:

<script runat="server">
Platform.Load("Core","1");

var de = Platform.Function.CreateObject("DataExtension");

Platform.Function.SetObjectProperty(de, "Name", "My Sendable DE"); 
Platform.Function.SetObjectProperty(de, "Description", "A DE created via SSJS"); 
Platform.Function.SetObjectProperty(de, "IsSendable", "true"); 
Platform.Function.SetObjectProperty(de, "IsTestable", "false"); 

var deFields = Platform.Function.CreateObject("DataExtensionField");
Platform.Function.SetObjectProperty(deFields, "FieldType", "Text"); 
Platform.Function.SetObjectProperty(deFields, "Name", "Id"); 
Platform.Function.SetObjectProperty(deFields, "MaxLength", 18); 
Platform.Function.SetObjectProperty(deFields, "IsPrimaryKey", "true"); 
Platform.Function.SetObjectProperty(deFields, "IsNillable", "false"); 
Platform.Function.SetObjectProperty(deFields, "IsRequired", "true"); 
Platform.Function.AddObjectArrayItem(de, "Fields", deFields);

Platform.Function.SetObjectProperty(de,"SendableDataExtensionField",deFields)

var deFields = Platform.Function.CreateObject("DataExtensionField");
Platform.Function.SetObjectProperty(deFields, "FieldType", "Text"); 
Platform.Function.SetObjectProperty(deFields, "Name", "Name"); 
Platform.Function.SetObjectProperty(deFields, "MaxLength", 50); 
Platform.Function.AddObjectArrayItem(de, "Fields", deFields);

var deFields = Platform.Function.CreateObject("DataExtensionField");
Platform.Function.SetObjectProperty(deFields, "FieldType", "EmailAddress"); 
Platform.Function.SetObjectProperty(deFields, "Name", "Email Address"); 
Platform.Function.SetObjectProperty(deFields, "IsNillable", "false"); 
Platform.Function.SetObjectProperty(deFields, "IsRequired", "true"); 
Platform.Function.AddObjectArrayItem(de, "Fields", deFields);

var subscriberAttr = Platform.Function.CreateObject("Attribute");
Platform.Function.SetObjectProperty(subscriberAttr, "Name", "Subscriber Key");
Platform.Function.SetObjectProperty(subscriberAttr, "Value", "Id");
Platform.Function.SetObjectProperty(de, "SendableSubscriberField", subscriberAttr);

var statusAndRequestID = [0,0];

var statMsg = Platform.Function.InvokeCreate(de, StatusAndRequestID, null);
Platform.Response.Write('status message: ' + statMsg);
</script>

In the above example, I've created the Subscriber relationship based on Subscriber Key = the Id field in my DE. However you could change this relationship to be based on email address by changing the following lines:

Platform.Function.SetObjectProperty(subscriberAttr, "Name", "Subscriber Key");
Platform.Function.SetObjectProperty(subscriberAttr, "Value", "Id");

To:

Platform.Function.SetObjectProperty(subscriberAttr, "Name", "Email Address");
Platform.Function.SetObjectProperty(subscriberAttr, "Value", "Email Address");
Related Topic