InvokeDelete
→ stringExecutes a SOAP Delete operation on a configured SOAP API object.
Syntax
Platform.Function.InvokeDelete(apiObject, status, options)
The official docs type the return value as an object, but at runtime the call returns the OverallStatus message as a string ("OK" / "Error"); status[0] receives the status message and status[1] a numeric request-id / error code. The documented separate statusMsgVar / errorCodeVar out-parameters are refuted at runtime — supplying that 4-argument form throws. The valid signature is 3 arguments (apiObject, status, options).
Show test script — string return value, status array, 3-argument arity and proof the delete took effect
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Callout: differs-from-docs — the return value, the status array and the
* argument count.
*
* Proves:
* 1. DEVIATION — the call returns a STRING, not the object the official
* docs promise. typeof is "string".
* 2. On success the returned string is the SOAP OverallStatus value "OK".
* 3. On failure the returned string is "Error" — proven with the SAME call
* shape, differing only in that the target was never created.
* 4. status[0] receives the status MESSAGE as a string
* ("Data Extension deleted." on a successful delete), never the literal
* "OK". A guard written against status[0] would therefore fire on a
* successful call; the value that equals "OK" is the RETURN value.
* 5. status[1] receives a NUMERIC code — 0 on success and the real SOAP
* error code 310007 for the not-found case. The docs describe this slot
* as a RequestID; at runtime it is a number, not a request-identifier
* string. There are no separate statusMsgVar / errorCodeVar
* out-parameters.
* 6. The valid signature is exactly THREE arguments
* (apiObject, status, options). Arity 0, 1, 2 and 4 all throw — there is
* no reachable optional argument in either direction. The 4-argument
* form the official docs describe is asserted here as a negative case so
* it cannot silently come back.
* 7. THE DELETE REALLY HAPPENS. The success/failure pair is not read off a
* status string alone: the same key is deleted a SECOND time and now
* answers with the not-found error, which is only possible if the first
* delete removed the object.
*
* DISCRIMINATING CONTROL for points 3, 5 and 7: the failing call is not a
* malformed call — it is the same object shape, pointed at a key that was
* never created. That is what makes "Error" plus code 310007 attributable to
* the API result rather than to a broken invocation.
*
* SCOPE: CloudPage only (MCDEV_Training_QA business unit). The page also
* lists automation availability; the automation context was not exercised.
*
* EXPECTED OUTPUT: every line starts with PASS. A FAIL means the runtime no
* longer matches the documented claim and the page must be revised.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}
/* Build a throwaway data extension definition. */
function newDataExtension(customerKey) {
var de = Platform.Function.CreateObject("DataExtension");
Platform.Function.SetObjectProperty(de, "CustomerKey", customerKey);
Platform.Function.SetObjectProperty(de, "Name", customerKey);
var field = Platform.Function.CreateObject("DataExtensionField");
Platform.Function.SetObjectProperty(field, "Name", "Email");
Platform.Function.SetObjectProperty(field, "FieldType", "Text");
Platform.Function.SetObjectProperty(field, "MaxLength", "100");
Platform.Function.SetObjectProperty(field, "IsPrimaryKey", "true");
Platform.Function.SetObjectProperty(field, "IsRequired", "true");
Platform.Function.AddObjectArrayItem(de, "Fields", field);
return de;
}
/* A delete payload only needs the key of the object to remove. */
function deleteTarget(customerKey) {
var de = Platform.Function.CreateObject("DataExtension");
Platform.Function.SetObjectProperty(de, "CustomerKey", customerKey);
return de;
}
var okKey = "ssjsguide_id_dfd";
var neverCreated = "ssjsguide_id_dfd_control";
/* Setup — create the object this script is going to delete. */
var setupStatus = [0, 0];
assert("setup: InvokeCreate of the throwaway data extension returns 'OK'", String(Platform.Function.InvokeCreate(newDataExtension(okKey), setupStatus, null)), "OK");
/* 1 + 2 + 4 + 5. The SUCCESS path. */
var okStatus = [0, 0];
var okResult = Platform.Function.InvokeDelete(deleteTarget(okKey), okStatus, null);
assert("DEV typeof InvokeDelete(...) is string (docs: the return value is an object)", String(typeof okResult), "string");
assert("DEV the return value is the OverallStatus string 'OK' (docs: a response object)", String(okResult), "OK");
assert("status[0] receives the status message on success", String(okStatus[0]), "Data Extension deleted.");
assert("status[0] is the MESSAGE, never the literal 'OK'", okStatus[0] !== "OK" ? "true" : "false", "true");
assert("DEV status[1] receives a NUMBER, not a RequestID string (docs: 'status and RequestID')", String(typeof okStatus[1]), "number");
assert("status[1] is the error code 0 on success", okStatus[1], 0);
assert("the status array keeps its length", okStatus.length, 2);
/* 3 + 5. The FAILURE path — same call shape, key that was never created. */
var errStatus = [0, 0];
var errResult = Platform.Function.InvokeDelete(deleteTarget(neverCreated), errStatus, null);
assert("DEV the failure return value is the OverallStatus string 'Error' (docs: a response object)", String(errResult), "Error");
assert("status[0] receives the not-found status message on failure", String(errStatus[0]), "Could not find the data extension definition. A valid object ID, customer key, or name must be provided to delete an existing data extension. ");
assert("status[1] is a numeric error code on failure", String(typeof errStatus[1]), "number");
assert("status[1] carries the real SOAP error code", errStatus[1], 310007);
/* 7. THE DELETE REALLY REMOVED THE OBJECT — the key now answers not-found. */
var goneStatus = [0, 0];
assert("proof of effect: deleting the same key AGAIN now returns 'Error'", String(Platform.Function.InvokeDelete(deleteTarget(okKey), goneStatus, null)), "Error");
assert("proof of effect: the second delete reports the not-found code 310007", goneStatus[1], 310007);
assert("proof of effect: the second delete reports the same not-found message as the control", String(goneStatus[0]), String(errStatus[0]));
/* 6. Exactly three arguments — no reachable optional argument. */
assertThrows("arity 0 throws (the valid arity is 3)", function () {
return Platform.Function.InvokeDelete();
});
assertThrows("arity 1 throws (the valid arity is 3)", function () {
return Platform.Function.InvokeDelete(deleteTarget("ssjsguide_id_a1"));
});
assertThrows("arity 2 throws - options is NOT optional (the valid arity is 3)", function () {
var s = [0, 0];
return Platform.Function.InvokeDelete(deleteTarget("ssjsguide_id_a2"), s);
});
assertThrows("arity 4 throws - there are no statusMsgVar / errorCodeVar out-parameters (the valid arity is 3)", function () {
var s = [0, 0];
return Platform.Function.InvokeDelete(deleteTarget("ssjsguide_id_a4"), s, null, null);
});
</script>
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
apiObject |
object | Yes | SOAP object built with CreateObject/SetObjectProperty |
status |
array | Yes | Array that receives the status and request ID of the API call (e.g. [0, 0]) |
options |
object | Yes | API configure options to include in the call. Can contain a null value. |
options may be null. status is an out parameter: the call writes the status
message into status[0] and a
numeric error code into status[1]. A null apiObject makes no SOAP call, returns
null, and leaves status untouched.
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Parameters —
* Platform.Function.InvokeDelete(apiObject, status, options)
*
* Proves, one parameter at a time:
* 1. apiObject must be a SOAP API object built with CreateObject and
* populated with SetObjectProperty. Such an object is a .NET CLR host
* object (typeof "clr"), and a call built that way succeeds.
* 2. A plain JavaScript object or a string as apiObject throws — the
* parameter is not structurally typed, it must be an
* ExactTarget.Integration.WSDL type.
* 3. A null apiObject is the one non-object that does NOT throw: no SOAP
* call is made, the return value is a genuine null (not undefined, and
* not an OverallStatus string) and the status array is left untouched.
* This mirrors the same finding on
* /platform-functions/invokecreate/ and /platform-functions/invokeconfigure/.
* 4. status must be an array and is an OUT parameter: it is mutated in
* place by the call, so the caller reads status[0] / status[1] after the
* call returns. Passing a non-array throws.
* 5. options is REQUIRED but may be null — the page's "can contain a null
* value" wording. Omitting it entirely (arity 2) throws, which is what
* makes "required, may be null" different from "optional".
* 6. The member exists: a successful 3-argument invocation is the only
* reliable existence proof for a Platform.Function member (typeof
* reports "clrmethodinfo" for every name, real or not, so it proves
* nothing and is deliberately NOT asserted here).
* 7. The delete performed by the documented 3-argument call really removed
* the object — asserted with the paired control, not with the status
* string alone.
*
* NOT ASSERTED: the values set on the apiObject cannot be read back from the
* object itself — it is a CLR host object and the engine blocks all
* introspection of it (see /platform-functions/createobject/). The values are
* proven indirectly by the API's own response.
*
* SCOPE: CloudPage only (MCDEV_Training_QA business unit).
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}
function assertNoThrow(id, fn) {
var ok = true, msg = "ok";
try { fn(); } catch (ex) { ok = false; msg = ex.message; }
Platform.Response.Write((ok ? "PASS " : "FAIL ") + id + " -> [" + msg + "]\n");
}
/* Build a throwaway data extension definition. */
function newDataExtension(customerKey) {
var de = Platform.Function.CreateObject("DataExtension");
Platform.Function.SetObjectProperty(de, "CustomerKey", customerKey);
Platform.Function.SetObjectProperty(de, "Name", customerKey);
var field = Platform.Function.CreateObject("DataExtensionField");
Platform.Function.SetObjectProperty(field, "Name", "Email");
Platform.Function.SetObjectProperty(field, "FieldType", "Text");
Platform.Function.SetObjectProperty(field, "MaxLength", "100");
Platform.Function.SetObjectProperty(field, "IsPrimaryKey", "true");
Platform.Function.SetObjectProperty(field, "IsRequired", "true");
Platform.Function.AddObjectArrayItem(de, "Fields", field);
return de;
}
function deleteTarget(customerKey) {
var de = Platform.Function.CreateObject("DataExtension");
Platform.Function.SetObjectProperty(de, "CustomerKey", customerKey);
return de;
}
var deKey = "ssjsguide_id_params";
/* Setup — create the object this script will delete. */
var setupStatus = [0, 0];
assert("setup: InvokeCreate of the throwaway data extension returns 'OK'", String(Platform.Function.InvokeCreate(newDataExtension(deKey), setupStatus, null)), "OK");
/* 1. apiObject is a CreateObject SOAP object — a CLR host object. */
var apiObject = Platform.Function.CreateObject("DataExtension");
assert("typeof CreateObject('DataExtension') is clr", String(typeof apiObject), "clr");
assertNoThrow("SetObjectProperty(apiObject, 'CustomerKey', ...) succeeds", function () {
Platform.Function.SetObjectProperty(apiObject, "CustomerKey", deKey);
});
/* 4 + 5 + 6 + 7. The documented 3-argument call with options = null. */
var status = [0, 0];
assert("InvokeDelete(apiObject, status, null) returns 'OK'", String(Platform.Function.InvokeDelete(apiObject, status, null)), "OK");
assert("status is an OUT parameter: status[0] was written by the call", String(status[0]), "Data Extension deleted.");
assert("status is an OUT parameter: status[1] was written by the call", status[1], 0);
var goneStatus = [0, 0];
assert("the delete took effect: the same key now returns 'Error'", String(Platform.Function.InvokeDelete(deleteTarget(deKey), goneStatus, null)), "Error");
assert("the delete took effect: the not-found code is 310007", goneStatus[1], 310007);
/* 2. apiObject must be a real SOAP object. */
assertThrows("a plain JavaScript object as apiObject throws", function () {
var s = [0, 0];
return Platform.Function.InvokeDelete({}, s, null);
});
assertThrows("a string as apiObject throws", function () {
var s = [0, 0];
return Platform.Function.InvokeDelete("DataExtension", s, null);
});
/* 3. null apiObject: no SOAP call is made — genuine null back, status untouched. */
var nullStatus = [0, 0];
var nullResult = Platform.Function.InvokeDelete(null, nullStatus, null);
assert("a null apiObject does NOT throw", nullResult === null ? "true" : "false", "true");
assert("a null apiObject returns a genuine null, not the OverallStatus string", String(typeof nullResult), "object");
assert("a null apiObject is not undefined", nullResult === undefined ? "true" : "false", "false");
assert("a null apiObject leaves status[0] untouched (no SOAP call was made)", nullStatus[0], 0);
assert("a null apiObject leaves status[1] untouched (no SOAP call was made)", nullStatus[1], 0);
/* 4. status must be an array. */
assertThrows("a non-array status throws", function () {
return Platform.Function.InvokeDelete(deleteTarget("ssjsguide_id_p1"), "notanarray", null);
});
/* 5. options is required — omitting it is NOT the same as passing null. */
assertThrows("omitting options (arity 2) throws - options is required, not optional", function () {
var s = [0, 0];
return Platform.Function.InvokeDelete(deleteTarget("ssjsguide_id_p2"), s);
});
</script>
Examples
var sub = Platform.Function.CreateObject("Subscriber");
Platform.Function.SetObjectProperty(sub, "SubscriberKey", "sub_123");
var StatusAndRequestID = [0, 0];
var result = Platform.Function.InvokeDelete(sub, StatusAndRequestID, null);
var status = StatusAndRequestID[0];
var requestID = StatusAndRequestID[1];
Test the return value against "OK", not status[0] — status[0] carries the status
message ("Data Extension deleted." when deleting a data extension), so a guard on it
fires even when the delete succeeded.
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Examples — the CreateObject / SetObjectProperty / InvokeDelete
* build-and-delete pattern, end to end, plus the status handling the example
* demonstrates.
*
* The page's example deletes a Subscriber. Both object types are exercised
* here: the Subscriber shape exactly as written on the page, and a throwaway
* DataExtension that this script creates itself so that the DELETE can be
* proven to have actually removed something. The values set on the apiObject
* CANNOT be read back from the object (it is a CLR host object — see
* /platform-functions/createobject/), so the only way to prove the delete
* took effect is to make the API answer for it.
*
* Proves:
* 1. The example's shape works: an apiObject built with CreateObject +
* SetObjectProperty, passed to InvokeDelete with a [0, 0] status array
* and null options, returns an OverallStatus string.
* 2. The two variables the example reads are exactly the two array slots:
* status = StatusAndRequestID[0] is the message string, requestID =
* StatusAndRequestID[1] the numeric code.
* 3. status[0] is the MESSAGE, never the literal "OK" — so a guard written
* against the status slot would fire even on a successful delete. The
* value that equals "OK" is the RETURN value.
* 4. ROUND-TRIP PROOF that the delete really took effect — the
* DISCRIMINATING CONTROL is a pair of otherwise identical delete calls:
* - deleting the object just created returns "OK" /
* "Data Extension deleted." / 0;
* - deleting a key that was never created returns "Error" with SOAP
* error code 310007.
* A delete that had silently done nothing would leave the object in
* place, so the re-delete would keep succeeding. It does not.
* 5. The script leaves nothing behind: after the round-trip delete, a
* further delete of the same key reports the not-found error.
* 6. The page's Subscriber example, run against a subscriber key that does
* not exist, is answered by the API itself — "Error" with the
* subscriber-not-found message and code 12001. That is the API
* rejecting a target, not the function failing, and it proves the
* Subscriber payload really reached the SOAP endpoint.
*
* SCOPE: CloudPage only (MCDEV_Training_QA business unit).
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertNoThrow(id, fn) {
var ok = true, msg = "ok";
try { fn(); } catch (ex) { ok = false; msg = ex.message; }
Platform.Response.Write((ok ? "PASS " : "FAIL ") + id + " -> [" + msg + "]\n");
}
function newDataExtension(customerKey) {
var de = Platform.Function.CreateObject("DataExtension");
Platform.Function.SetObjectProperty(de, "CustomerKey", customerKey);
Platform.Function.SetObjectProperty(de, "Name", customerKey);
var field = Platform.Function.CreateObject("DataExtensionField");
Platform.Function.SetObjectProperty(field, "Name", "Email");
Platform.Function.SetObjectProperty(field, "FieldType", "Text");
Platform.Function.SetObjectProperty(field, "MaxLength", "100");
Platform.Function.SetObjectProperty(field, "IsPrimaryKey", "true");
Platform.Function.SetObjectProperty(field, "IsRequired", "true");
Platform.Function.AddObjectArrayItem(de, "Fields", field);
return de;
}
function deleteTarget(customerKey) {
var de = Platform.Function.CreateObject("DataExtension");
Platform.Function.SetObjectProperty(de, "CustomerKey", customerKey);
return de;
}
var deKey = "ssjsguide_id_example";
var neverCreated = "ssjsguide_id_example_control";
/* Setup — create the object the example is going to delete. */
var setupStatus = [0, 0];
assert("setup: InvokeCreate of the throwaway data extension returns 'OK'", String(Platform.Function.InvokeCreate(newDataExtension(deKey), setupStatus, null)), "OK");
/* 1 + 2. The page's example shape, against the object just created. */
var obj = Platform.Function.CreateObject("DataExtension");
assert("typeof CreateObject('DataExtension') is clr", String(typeof obj), "clr");
assertNoThrow("SetObjectProperty(obj, 'CustomerKey', ...) succeeds", function () {
Platform.Function.SetObjectProperty(obj, "CustomerKey", deKey);
});
var StatusAndRequestID = [0, 0];
var result = Platform.Function.InvokeDelete(obj, StatusAndRequestID, null);
assert("InvokeDelete(obj, StatusAndRequestID, null) returns 'OK'", String(result), "OK");
var status = StatusAndRequestID[0];
var requestID = StatusAndRequestID[1];
assert("status = StatusAndRequestID[0] is the message string", String(status), "Data Extension deleted.");
assert("requestID = StatusAndRequestID[1] is the numeric code 0 on success", requestID, 0);
/* 3. The status slot is the message, not the OverallStatus string. */
assert("status !== 'OK' on a SUCCESSFUL delete - the OverallStatus string is the RETURN value", status !== "OK" ? "true" : "false", "true");
assert("the value that equals 'OK' is the return value, not status[0]", result === "OK" ? "true" : "false", "true");
/* 4. CONTROL — the delete that must FAIL, on a key never created. */
var controlStatus = [0, 0];
assert("control: deleting a data extension that was never created returns 'Error'", String(Platform.Function.InvokeDelete(deleteTarget(neverCreated), controlStatus, null)), "Error");
assert("control: status[1] carries SOAP error code 310007", controlStatus[1], 310007);
/* 5. The delete really removed the object — it now answers like the control. */
var afterStatus = [0, 0];
assert("proof of effect: deleting the same key again now reports 'Error'", String(Platform.Function.InvokeDelete(deleteTarget(deKey), afterStatus, null)), "Error");
assert("proof of effect: status[1] carries SOAP error code 310007", afterStatus[1], 310007);
assert("proof of effect: the message matches the never-created control", String(afterStatus[0]), String(controlStatus[0]));
/* 6. The page's Subscriber example — the payload reaches the SOAP endpoint. */
var sub = Platform.Function.CreateObject("Subscriber");
Platform.Function.SetObjectProperty(sub, "SubscriberKey", "ssjsguide_id_sub_never");
var subStatus = [0, 0];
var subResult = Platform.Function.InvokeDelete(sub, subStatus, null);
assert("the Subscriber example returns an OverallStatus string", String(typeof subResult), "string");
assert("deleting a subscriber key that does not exist returns 'Error'", String(subResult), "Error");
assert("the API itself answered the Subscriber payload", String(subStatus[0]), "The subscriber was not found.");
assert("the subscriber-not-found SOAP error code is 12001", subStatus[1], 12001);
</script>