Skip to main content

Transformations

CarrierX Core API allows the partners to additionally manipulate the data of the incoming and outgoing calls using transformations.

tip

Refer to our Set up Transformations Using CarrierX Portal quick start guide for the detailed description on how you can use transformations with the help of CarrierX portal.

What Are Transformations and Why Use Them

The users might find transformations quite complicated, but the concept behind the transformations is very simple: you can check the inbound or outbound call data and modify it so that it better matched your purposes.

Why would one even bother with this?

It might happen, that the application you use requires the call data (e.g., the phone number in a certain header field) to have a specific format. Rather than process it on the application side (especially, when you are not the developer of that application, or cannot modify it due to some other reasons), you can apply the transformations within CarrierX and send the data to your application in the format it requires.

Or vice versa, sometimes the application might send the data to CarrierX in a format it cannot accept properly, and this data format cannot be changed on the application side. You can use the transformations to adapt the data into the CarrierX compatible format for the correct work.

The logic of a simple rewrite and set transformation looks like the following:

Rewrite Transformations

note

The logic will be reversed when the data goes from the application to CarrierX.

More complex transformations include lookup transformations and conditional transformations. The former will lookup for the routing number and transform the call fields depending on the result. The latter will allow the users to check the incoming data against some condition and then apply the matching transformations (simple, lookup, or other conditional) depending on the check results.

You can also combine different types of transformations applying them one-by-one, e.g., first perform lookup, then use some simple transformation, then check for a condition and, if true, use more simple transformations, among which are the STIR/SHAKEN, reject transformations, and others.

Transformations Levels

Depending on the object where the transformations are set, they can be applied to different calls on different levels.

These transformations levels include:

  • Partner—transformations set to the Partner object will be applied to all the calls for the selected partner.
  • DID—transformations set to the DID object will be applied to the calls to/from the specified phone number, trunk groups, trunks, and endpoints associated with this phone number.
  • Prefix—transformations set to the Prefix object will be applied to the calls routed by the specified prefix, as well as the trunk groups, trunks, and endpoints for which this prefix routes the traffic.
  • Trunk Group—transformations set to the Trunk Group object will be applied to the calls routed through the specified trunk group, as well as the trunks inside this trunk group and the endpoints associated with the trunks within this trunk group.
  • Trunk—transformations set to the Trunk object will be applied to the calls routed through the specified trunk, as well as the endpoints associated with this trunk.
  • Endpoint—transformations set to the Endpoint object will be applied to the calls routed to or from this endpoint.
note

You can specify the direction of the calls affected by a specific transformation (only outgoing, or only incoming, or all the calls). Refer to the Transformations Format section below for more information on how to do this.

This way, you can use the partner level to set transformations which will be applied to all the calls (inbound or outbound) for which you use your rented phone numbers or specified prefixes. These transformations will be active throughout CarrierX system for you as a partner.

To narrow the rules to a specific DID or prefix and other objects associated with it, and at the same time exclude other phone numbers or prefixes, use transformations on DID/prefix level.

Trunk groups, trunks, and endpoints levels will help apply the transformations to the call data passing through them, and will not affect other trunk groups, trunks or endpoints.

Transformations Format

Any transformation is an object with three fields:

  • action is the name of the transformation and a short description of an action this transformation performs, i.e., what type of modification will be made. For example, the transformation with the reject action actually rejects the call returning one of the reasons set in the operands.

  • direction defines the direction of the call this transformation will be applied to. For example, the transformation with the inbound direction will be applied to the incoming calls only, and will not affect the outgoing calls. Refer to this section for more information on CarrierX definitions of the inbound and outbound calls.

  • operands are the items to which the action is applied. Some of the operands can include only set values, and some accept both set values and regular expressions.

action and direction are the required fields when creating a transformation.

The presence and number of operands depend on the action. While the operands field itself must always be present, the number of operands differ from one transformation to another.

tip

Most of the transformations require at least one operand. Some can accept up to 100 operands. There are also transformations that do not require any operands.

A typical transformation will have the following structure:

{
"action": "set_header_parameter",
"direction": "any",
"operands": ["P-Charging-Vector","orig-ioi","privateSIP"]
}

We will take a closer look at different transformations and their attributes in the section below.

Transformations and Their Examples Explained

In this section we will explain the main types of CarrierX transformations and the operands used with them. We will also see the examples for main transformation types to understand what they do more easily.

Header Transformations

Header Transformations are used to transform single or multiple call headers or header parameters. There are two types of header transformations: rewrite transformations and set transformations.

Rewrite Transformations

Quite often it is necessary to rewrite a single or multiple call headers or header parameters. This can be done with the help of rewrite transformations:

Rewrite Transformations

The rewrite transformation will analyze the call data, find the source or destination phone number, or the header set by the action and, depending on the action, will replace either the phone number/header or some of the header parameters.

rewrite_from/rewrite_to

The rewrite_from transformation will replace the phone number which is the originator of the call (the source phone number). Its syntax looks like the following:

{
"action": "rewrite_from",
"direction": "any",
"operands": [
"pattern",
"replace"
]
}

The rewrite_to transformation does the same to the phone number which is the destination of the call. Its syntax looks like the following:

{
"action": "rewrite_to",
"direction": "any",
"operands": [
"pattern",
"replace"
]
}
Example
Example

The software you use at your third-party endpoint only understands the phone number when it has exactly 11 digits with 1 as the first digit (the E.164 format for the US and Canada phone numbers). But the call information might lack this first digit, and you will need to modify the data checking it and adding 1 if it is missing.

Initially, the From header looks like this:

From: "John Smith" <sip:5162065613@12.7.193.174>;tag=as062a2e2a

The transformation syntax will be the following:

{
"action": "rewrite_from",
"direction": "any",
"operands": [
"^([2-9]\\d{9})$",
"1\\1"
]
}
  • The first operand (pattern = ^([2-9]\d{9})$) is the regular expression used to find out whether the phone number lacks 1 at the beginning.
  • The second operand (replace = 1\1) adds 1 to the beginning of the found combination of digits (i.e., the phone number) in case the pattern matches.

After the transformation, the From header will look the following way:

From: "John Smith" <sip:15162065613@12.7.193.174>;tag=as062a2e2a

The same example for the rewrite_to transformation will only differ in the action value.

rewrite_from_header_param/rewrite_to_header_param

The rewrite_from_header_param transformation will replace the parameters of the From header with the data specified. Its syntax looks like the following:

{
"action": "rewrite_from_header_param",
"direction": "any",
"operands": [
"parameter",
"pattern",
"replace"
]
}

The rewrite_to_header_param transformation does the same to the To header. Its syntax looks like the following:

{
"action": "rewrite_to_header_param",
"direction": "any",
"operands": [
"parameter",
"pattern",
"replace"
]
}
Example
Example

You need to update the cnam parameter of the From header adding the * special character to it. This will mean that the call is from a trusted caller.

Initially, the From header looks like this:

From: "John Smith" <sip:15162065613@12.7.193.174>;tag=as062a2e2a

The transformation syntax will be the following:

{
"action": "rewrite_from_header_param",
"direction": "any",
"operands": [
"cnam",
"(.{1,14})",
"\\1*"
]
}
  • The first operand (parameter = cnam) will make the transformation look for the cnam parameter of the From header.
  • The second operand (pattern = (.{1,14})) defines the the match, it will search for the caller ID in the cnam parameter.
  • If such a match is found, it will be replaced. The \\1* regular expression will add the * character to the end of the caller ID.

After the transformation, the From header will look the following way:

From: "John Smith*" <sip:15162065613@12.7.193.174>;tag=as062a2e2a

The same example for the rewrite_to_header_param transformation will only differ in the action value.

rewrite_header

The rewrite_header transformation will replace the header (or a part of it) you specify as an operand with the new values, or create it, in the case the call data lacks it. Its syntax looks like the following:

{
"action": "rewrite_header",
"direction": "any",
"operands": [
"header",
"pattern",
"replace",
"default"
]
}
Example
Example

The software you use at your third-party endpoint requires the presence of the X-Custom-Header header with the 6060 port specified. But the call data either contains the 5060 port in this header or completely lacks this header.

Initially, the X-Custom-Header header looks like this:

X-Custom-Header: sip:10.1.5.200:5060

The transformation syntax will be the following:

{
"action": "rewrite_header",
"direction": "any",
"operands": [
"X-Custom-Header",
":5060",
":6060",
"sip:10.1.5.200:6060"
]
}
  • The first operand (header = X-Custom-Header) specifies the header which must be found
  • The second operand (pattern = :5060) defines the pattern to find the port which will be replaced.
  • The third operand (replace = :6060) specifies the value with which the pattern must be replaced.
  • We also add the fourth operand (default = sip:10.1.5.200:6060) to make sure that in the case the header is missing from the call data it will be created and set to this value.

After the transformation, the X-Custom-Header header will look the following way:

X-Custom-Header: sip:10.1.5.200:6060

rewrite_header_parameter

The rewrite_header transformation will replace the parameter of the header you specify as an operand with the new value, or create it, in the case the call data lacks it. Its syntax looks like the following:

{
"action": "rewrite_header_parameter",
"direction": "any",
"operands": [
"header",
"parameter",
"pattern",
"replace",
"default"
]
}
Example
Example

The software you use at your third-party endpoint requires the presence of the Remote-Party-ID header with its privacy parameter set to cnam. But the call information either contains the name value in this header parameter or completely lacks it.

Initially, the Remote-Party-ID header looks like this:

Remote-Party-ID: "John Smith" <sip:15162065613@10.1.10.190>;party=calling;privacy=name;screen=no

The transformation syntax will be the following:

{
"action": "rewrite_header_parameter",
"direction": "any",
"operands": [
"Remote-Party-ID",
"privacy",
"name",
"cnam",
"cnam"
]
}
  • The first operand (header = Remote-Party-ID) specifies the header which must be found.
  • The second operand (parameter = privacy) defines the parameter of the selected header, which must be modified.
  • The third operand (pattern = name) defines the pattern to find the port which will be replaced.
  • The fourth operand (replace = cnam) specifies the value with which the pattern must be replaced.
  • We also add the fifth operand (default = cnam) to make sure that in the case the header is missing from the call data it will be created and set to this value.

After the transformation, the Remote-Party-ID header will look the following way:

Remote-Party-ID: "John Smith" <sip:15162065613@10.1.10.190>;party=calling;privacy=cnam;screen=no

Set Transformations

In the case the required parameters are missing from the call data, they can be added to it with the help of set transformations.

Set Transformations

set_header

The set_header transformation will add a new header you specify as an operand to the call data. Its syntax looks like the following:

{
"action": "set_header",
"direction": "any",
"operands": [
"header",
"value"
]
}
note

If the value is set to an empty string and there is a pre-existing header, it will be cleared.

Example
Example

The software you use at your third-party endpoint requires the presence of the X-Custom-Header header with the 5060 port specified. But the call data completely lacks this header.

Initially, the X-Custom-Header header is not present in the call data.

The transformation syntax will be the following:

{
"action": "set_header",
"direction": "any",
"operands": [
"X-Custom-Header",
"sip:10.1.5.200:5060"
]
}

After the transformation, the X-Custom-Header header will look the following way:

X-Custom-Header: sip:10.1.5.200:5060

set_header_parameter

The set_header_parameter transformation will add a new parameter to the header you specify as an operand. Its syntax looks like the following:

{
"action": "set_header_parameter",
"direction": "any",
"operands": [
"header",
"parameter",
"value"
]
}
Example
Example

You need to add the orig-ioi parameter with the privateSIP value to the call P-Charging-Vector header.

Initially, the P-Charging-Vector header looks like this:

P-Charging-Vector: icid-value=ab5fc4ee59;icid-generated-at=12.7.193.171

The transformation syntax will be the following:

{
"action": "set_header_parameter",
"direction": "any",
"operands": [
"P-Charging-Vector",
"orig-ioi",
"privateSIP"
]
}
  • The first operand (header = P-Charging-Vector) specifies the header, to which the parameter will be added.
  • The second operand (parameter = orig-ioi) defines the parameter to add.
  • And the third operand (value = privateSIP) sets the required value to the new header parameter.

After the transformation, the P-Charging-Vector header will look the following way:

P-Charging-Vector: icid-value=ab5fc4ee59;icid-generated-at=12.7.193.171;orig-ioi=privateSIP

Lookup Transformations

It is also possible to perform more complex transformations, e.g., lookup the routing number and transform the call fields depending on the result.

Lookup Transformations

lookup_rn

The lookup_rn information will lookup the routing number and return it so that it could be used instead of the source or destination number. Its syntax looks like the following:

{
"action": "lookup_rn",
"direction": "inbound",
"operands": [
"force",
"always",
"phonenumber",
"destination",
"on_failure",
"input_format",
"output_format_domestic",
"output_format_international",
"output_format_guess_not_found"
]
}
Example
Example

The software you use at your third-party endpoint only understands the phone number when it has exactly 11 digits with a + and 1 as the first digit (the E.164 format with a plus for the US and Canada phone numbers), and also needs to have the routing number rather than the source number in the From header. But the call information might show only the call source number. You will need to perform routing number lookup and place it to the From header instead of the source number.

Initially, the From header looks like this:

From: "John Smith" <sip:15162065613@12.7.193.174>;tag=as062a2e2a

The transformation syntax will be the following:

{
"action": "lookup_rn",
"direction": "inbound",
"operands": [
"true",
"true",
"{{src}}",
"from",
"ignore",
"guess",
"e164_with_plus",
"e164_with_plus",
"e164_with_plus"
]
}
  • The first operand (force = true) will make the transformation to always lookup the routing number, even if the npdi field is already set in the SIP URI.
  • The second operand (always = true) will always add the routing number to the destination field.
  • The third operand (phonenumber = {{src}}) will lookup the source number (or the calling party).
  • The fourth operand (destination = from) will set the field where to store the routing number.
  • The fifth operand (on_failure = ignore) will define the behavior on the transformation lookup request failure, setting it to ignore.
  • The sixth operand (input_format = guess) will try and guess the phone number input format before performing the lookup for it.
  • The seventh operand (output_format_domestic = e164_with_plus) will define the output format for the found number as E.164 (11 digits) with a + at the beginning in the case the number is considered domestic.
  • The eighth operand (output_format_international = e164_with_plus) will define the output format for the found number as E.164 (11 digits) with a + at the beginning in the case the number is considered international.
  • And the ninth operand (output_format_guess_not_found = e164_with_plus) will define the output format for the phone number as E.164 (11 digits) with a + at the beginning in the case the routing number could not be found.

Note, that fields in double curly brackets are called expandable macro variables. To see the full list of them, please refer to the Expandable Macro Variables Appendix.

After the transformation, the From header will look the following way:

From: "John Smith" <sip:+16466531111@12.7.193.174>;tag=as062a2e2a

STIR/SHAKEN Transformations

The STIR/SHAKEN transformations are used to check the calling party, validate it, and add the appropriate mark to the call data depending on the attestation result. Refer to the STIR/SHAKEN section for more information about this.

stir_validate

The stir_validate transformation will validate the call and return data that can be used with other transformations.

STIR Validate Transformation

Its syntax looks like the following:

{
"action": "stir_validate",
"direction": "any",
"operands": []
}
Example
Example

To receive the validation data about the call, set the following transformation:

{
"action": "stir_validate",
"direction": "any",
"operands": []
}

As a result, it will return the following data:

  • {{stir_attest}} for the attestation level used for the call.
  • {{stir_origid}} for the ID of the call originator.
  • {{stir_verstat}} for the TN validation result (available values include TN-Validation-Passed, TN-Validation-Failed, and No-TN-Validation).

Note, that fields in double curly brackets are called expandable macro variables. To see the full list of them, please refer to the Expandable Macro Variables Appendix.

The system saves the verification results to the stir_attest, stir_origid, and stir_verstat attributes of the Call Detail Record object.

These results can be used, for example, with the conditional transformations for the further actions that will depend on the validation result.

Conditional Transformations

The conditional transformations are normally used when there is a more complex logic behind them. They allow the users to check the incoming data against some condition and then apply the matching transformations (rewrite, lookup, other conditional, etc) depending on the check results.

Conditional Transformations

Multiple conditional transformations can be applied to one and the same call, each of them will trigger some other transformation depending on the rule matched.

if_match

The if_match transformation will add conditions based on which other transformations are applied. Its syntax looks like the following:

{
"action": "if_match",
"direction": "inbound",
"operands": [
"value",
"match",
"action",
"arg1",
"argX"
]
}
note

The if_match transformation can accept up to 100 operands, but the arg1--argX operands are optional, as they depend on the action and its required operands.

Example
Example

You need to reject all the calls that failed the validation.

The transformation syntax will be the following:

{
"action": "if_match",
"direction": "inbound",
"operands": [
"{{stir_verstat}}",
"TN-Validation-Failed",
"reject",
"forbidden"
]
}
  • The first operand (value = {{stir_verstat}}) specifies the value against which the match will be done. In this example, it might be equal to one of the following values: TN-Validation-Passed, TN-Validation-Failed, or No-TN-Validation. These values are returned when the stir_validate transformation is used.
  • The second operand (match = TN-Validation-Failed) sets the value the transformation will be looking for. If this value matches the first operand, the action from the next operands will be executed.
  • The third operand (action = reject) defines the transformation that will be executed if the condition matches.
  • And the fourth operand (arg1 = forbidden) is the operand required by the transformation defined in the action (in this example it is reject).

Note, that fields in double curly brackets are called expandable macro variables. To see the full list of them, please refer to the Expandable Macro Variables Appendix.

The result of this transformation (if the condition is true) will be that the call that failed the validation will be rejected with the forbidden reason.

Other Transformations

reject

The reject transformation will drop the calls with one of the supported reasons.

Reject Transformation

Its syntax looks like the following:

{
"action": "reject",
"direction": "inbound",
"operands": [
"reason",
"message"
]
}
note

Only the reason operand is required. The message operand can be omitted. No message will be returned to the caller in this case.

Example
Example

You need to reject the inbound calls with the busy-here reason and send the additional 'My reason for rejecting the call' message to inform the caller about the reject reason.

The transformation syntax will be the following:

{
"action": "reject",
"direction": "inbound",
"operands": [
"busy-here",
"My reason for rejecting the call"
]
}
  • The first operand (reason = busy-here) defines the reason that will be passed to the inbound call, and the call will be dropped.

  • The second operand (message = My reason for rejecting the call) defines the additional message that will be sent to the caller as a part of the Call-Info SIP header:

Call-Info: "My reason for rejecting the call"

set_user_data

The set_user_data transformation will add custom user data to the call detail records. The transformation saves the data as a JSON object to the user_data attribute of the Call Detail Record object. Its syntax looks like the following:

{
"action": "set_user_data",
"direction": "any",
"operands": [
"key",
"value"
]
}
Example
Example

You need to save the SIP Identity header information to the call detail record.

The transformation syntax will be the following:

{
"action": "set_user_data",
"direction": "any",
"operands": [
"identity",
"{{SipHeader_Identity}}"
]
}
  • The first operand (key = identity) specifies the name of the key that will be used to store the user-defined data.
  • And the second operand (value = {{SipHeader_Identity}}) takes the value from the SIP Identity header and sets it to the new key. Fields in double curly brackets are called expandable macro variables. To see the full list of them, please refer to the Expandable Macro Variables Appendix.

After the transformation, the user_data attribute of the call detail record will look the following way:

{
"user_data": {
"identity": "eyJ0eXAiOiJwYXNzcG9ydCIsImFsZyI6I...alg=ES256;ppt=shaken"
}
}

sms_normalize

By default, all phone numbers for the SMS Object are always treated as E.164 international numbers.

The sms_normalize action is used to add a corresponding country prefix to the SMS Object from and/or to fields to allow local in-country formats. This transformation is based on the Phonenumber Lookup object mechanism and the Phonenumber Lookup logic.

SMS Normalize Transformation

Its syntax looks like the following:

{
"action": "sms_normalize",
"direction": "outbound",
"operands": [
"guess",
"country_code",
"field",
"on_failure",
"output_format"
]
}
Example
Example

You want all outbound SMS messages with domestic number format in the to field to be automatically routed to phone numbers inside a particular country by default. For that purpose, you can indicate the country_code you need as one of the operands, and the system will be automatically converting such domestic numbers to the E.164 format of that exact country by adding the country code you have specified.

The transformation syntax will be the following:

{
"action": "sms_normalize",
"direction": "outbound",
"operands": [
"e164",
"USA",
"to",
"ignore",
"e164"
]
}
  • The first operand (guess = e164) tells the system which to prefer if the country_code lookup step (see below) results in finding out that the DID this transformation is applied to is both: a valid E.164 and a valid domestic in_country phone number. The default value is e164. In this case the system will make a guess that the DID is an E.164 number. Another possible value for this operand is in_country in which case the system will try to make a guess that the DID is a domestic number. If the guess step does not bring any result, the system proceeds to the on_failure step.

  • The second operand (country_code = USA) tells the system that before routing any outbound SMS to a phone number without the + prefix, it should first check and verify whether it is a valid number in that country. If a valid number is found, the system will add the corresponding country code prefix to the phone number and the SMS will be processed further, i.e. for the USA, the +1 prefix will be added, and no further checks will be made. If no valid number is found, however, the system will try to find a match for this number among domestic (in-country) and E.164 numbers. Here, tree options are possible:

    • if a match is found and the number is only a valid domestic number or only a valid E.164 number, the SMS will be processed further, without any more checks. If the number is a domestic one, the corresponding code of that country will be added (i.e. such domestic number will be converted to the E.164 format), and if the number is E.164, it will be processed as is, without changes.
    • if the number matches both, domestic and E.164 formats, the system will switch to the guess step (see above).
    • if no match is found, the system will switch to the on_failure step (see below) and will return a 4xx error.
note

If no country_code is set at all, the system uses country_code = USA by default.

  • The third operand (field = to) tells the system that this transformation will be applied to the to field of the affected SMS Object. Another possible value you could use here is from.

  • The fourth operand (on_failure = ignore) tells the system to ignore the fact that the phone number has not been identified successfully and to continue with sending the SMS.

  • The fifth operand (output_format=e164) tells the system to output the destination DID in the E.164 format.

The sequence of operands in this transformation may look confusing at first. But here is a flow chart of how the sms_normalize transformation works.

SMS Normalize Transformation

Chaining Transformations

Sometimes, it might be necessary to use multiple transformations rather than a single one. In this case, the actions can be chained, and the next transformations will either be using the results of the previous ones, or cover cases which the previous transformations missed.

Let's see what the following succession of transformations does:

"transformations": [
{
"action": "stir_validate",
"direction": "inbound",
"operands": []
},
{
"action": "set_header",
"direction": "inbound",
"operands": ["X-StirResult", "{{stir_verstat}}-{{stir_attest}}"]
},
{
"action": "if_match",
"direction": "inbound",
"operands": ["{{stir_verstat}}:{{stir_attest}}", "TN-Validation-Passed:[AB]", "rewrite_from_header_param", "cnam", "(.{1,14})", "\\1*"]
},
{
"action": "if_match",
"direction": "inbound",
"operands": ["{{stir_verstat}}", "No-TN-Validation", "rewrite_from_header_param", "cnam", ".*", "POSSIBLE FRAUD"]
},
{
"action": "if_match",
"direction": "inbound",
"operands": ["{{stir_verstat}}", "TN-Validation-Failed", "reject", "forbidden"]
}
]
  • The stir_validate transformation validates the inbound call and returns the {{stir_attest}} and {{stir_verstat}} variables, which will be used with the next transformations.

  • The set_header transformation adds the X-StirResult header to the call data and sets its value to the received {{stir_verstat}}-{{stir_attest}} (e.g., TN-Validation-Passed-A). Note, that fields in double curly brackets are called expandable macro variables. To see the full list of them, please refer to the Expandable Macro Variables Appendix.

    After the transformation

    X-StirResult: TN-Validation-Passed-A
  • The first if_match transformation checks the following condition: if the call is validated A or B ({{stir_attest}} = A or {{stir_attest}} = B and {{stir_verstat}} = TN-Validation-Passed), the rewrite_from_header_param transformation will add a special * character to the end cnam parameter of the From header to signify a trusted caller.

    Before the transformation

    X-StirResult: TN-Validation-Passed-A
    From: "John Smith" <sip:15162065613@12.7.193.174>;tag=as062a2e2a

    After the transformation

    X-StirResult: TN-Validation-Passed-A
    From: "John Smith*" <sip:15162065613@12.7.193.174>;tag=as062a2e2a
  • The second if_match transformation checks the following condition: if the call does not have an Identity header and because of that has the {{stir_verstat}} set to No-TN-Validation, the rewrite_from_header_param transformation will replace the whole cnam parameter of the From header with the POSSIBLE FRAUD value, signifying that the call might be from an unwanted caller.

    Before the transformation

    X-StirResult: No-TN-Validation-
    From: "John Smith" <sip:15162065613@12.7.193.174>;tag=as062a2e2a

    After the transformation

    X-StirResult: No-TN-Validation-
    From: "POSSIBLE FRAUD" <sip:15162065613@12.7.193.174>;tag=as062a2e2a
  • The last if_match transformation checks the following condition: if the call has an Identity header present but failed validation and the has the {{stir_verstat}} set to TN-Validation-Failed, such call is considered definitely unwanted and is rejected.

    Before the transformation

    X-StirResult: TN-Validation-Failed-
    From: "John Smith" <sip:15162065613@12.7.193.174>;tag=as062a2e2a

The above transformations logic looks like the following:

Chaining Transformations

Further Reading

Transformations API Reference

Refer to the Transformations API reference to get the complete list of their attributes and methods used with them:

Administrator Transformations