

# AWS AppSync resolver mapping template reference (VTL)
<a name="resolver-mapping-template-reference"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The following sections will describe how utility operations can be used in mapping templates:
+  [ Resolver mapping template overview ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-overview.html) - Learn more about how resolvers work in AWS AppSync.
+  [ Resolver mapping template programming guide ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-programming-guide.html) - Learn more about basic VTL data structures and logic handling.
+  [ Resolver mapping template context reference ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html) - Learn more about the context map and how it's used in resolvers.
+  [ Resolver mapping template utility reference ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html) - Learn more about using utilities to simplify code.
+  [ Resolver mapping template reference for DynamoDB ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html) - Learn more about how resolvers interact with DynamoDB.
+  [ Resolver mapping template reference for RDS ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-rds.html) - Learn more about resolver structure and interactions with RDS.
+  [ Resolver mapping template reference for OpenSearch ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-elasticsearch.html) - Learn more about resolver request and response structure and interactions with OpenSearch Service.
+  [ Resolver mapping template reference for Lambda ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-lambda.html) - Learn more about resolver request and response structure and interactions with Lambda.
+  [ Resolver mapping template reference for EventBridge ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-eventbridge.html) - Learn more about resolver request and response structure and interactions with EventBridge.
+  [ Resolver mapping template reference for None data source ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-none.html) - Learn more about resolver request and response structure and interactions with NONE data sources.
+  [ Resolver mapping template reference for HTTP ](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-http.html) - Learn more about resolver request and response structure and interactions with HTTP endpoints.

# AWS AppSync resolver mapping template overview
<a name="resolver-mapping-template-reference-overview"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

AWS AppSync lets you respond to GraphQL requests by performing operations on your resources. For each GraphQL field you wish to run a query or mutation on, a resolver must be attached in order to communicate with a data source. The communication is typically through parameters or operations that are unique to the data source.

Resolvers are the connectors between GraphQL and a data source. They tell AWS AppSync how to translate an incoming GraphQL request into instructions for your backend data source, and how to translate the response from that data source back into a GraphQL response. They are written in the [Apache Velocity Template Language (VTL)](https://velocity.apache.org/engine/1.7/user-guide.html), which takes your request as input and outputs a JSON document containing the instructions for the resolver. You can use mapping templates for simple instructions, such as passing in arguments from GraphQL fields, or for more complex instructions, such as looping through arguments to build an item before inserting the item into DynamoDB. 

There are two types of resolvers in AWS AppSync that leverage mapping templates in slightly different ways:
+ Unit resolvers
+ Pipeline resolvers

## Unit resolvers
<a name="unit-resolvers"></a>

Unit resolvers are self-contained entities which include a request and response template only. Use these for simple, single operations such as listing items from a single data source.
+ Request templates: Take the incoming request after a GraphQL operation is parsed and convert it into a request configuration for the selected data source operation.
+ Response templates: Interpret responses from your data source and map it to the shape of the GraphQL field output type.

## Pipeline resolvers
<a name="pipeline-resolvers"></a>

Pipeline resolvers contain one or more *functions* which are performed in sequential order. Each function includes a request template and response template. A pipeline resolver also has a *before* template and an *after* template that surround the sequence of functions that the template contains. The *after* template maps to the GraphQL field output type. Pipeline resolvers differ from unit resolvers in the way that the response template maps output. A pipeline resolver can map to any output you want, including the input for another function or the *after* template of the pipeline resolver. 

 Pipeline resolver *functions* enable you to write common logic that you can reuse across multiple resolvers in your schema. Functions are attached directly to a data source, and like a unit resolver, contain the same request and response mapping template format.

The following diagram demonstrates the process flow of a unit resolver on the left and a pipeline resolver on the right.

![\[A diagram of a unit resolver that communicates with a single data source and a diagram of a pipeline resolver that communicates with multiple data sources.\]](http://docs.aws.amazon.com/appsync/latest/devguide/images/unit-pipeline-resolver.png)


Pipeline resolvers contain a superset of the functionality that unit resolvers support, and more, at the cost of a little more complexity.

### Anatomy of a pipeline resolver
<a name="anatomy-of-a-pipeline-resolver"></a>

A pipeline resolver is composed of a **Before** mapping template, an **After** mapping template, and a list of functions. Each function has a **request** and **response** mapping template that it executes against a data source. As a pipeline resolver delegates execution to a list of functions, it is therefore not linked to any data source. Unit resolvers and functions are primitives that execute operation against data sources. See the [Resolver mapping template overview](#aws-appsync-resolver-mapping-template-reference-overview) for more information.

#### Before mapping template
<a name="before-mapping-template"></a>

The request mapping template of a pipeline resolver, or the **Before** step, allows you to perform some preparation logic before executing the defined functions.

#### Functions list
<a name="functions-list"></a>

The list of functions a pipeline resolver will run in sequence. The pipeline resolver request mapping template evaluated result is made available to the first function as `$ctx.prev.result`. Each function output is available to the next function as `$ctx.prev.result`.

#### After mapping template
<a name="after-mapping-template"></a>

The response mapping template of a pipeline resolver, or the **After** step, allows you to perform some final mapping logic from the output of the last function to the expected GraphQL field type. The output of the last function in the functions list is available in the pipeline resolver mapping template as `$ctx.prev.result` or `$ctx.result`.

#### Execution flow
<a name="execution-flow"></a>

Given a pipeline resolver comprised of two functions, the list below represents the execution flow when the resolver is invoked:

![\[GraphQL request flow diagram showing template processing and data source interactions.\]](http://docs.aws.amazon.com/appsync/latest/devguide/images/PipelineResolver.jpg)


1. Pipeline resolver **Before** mapping template

1. Function 1: Function request mapping template

1. Function 1: Data source invocation

1. Function 1: Function response mapping template

1. Function 2: Function request mapping template

1. Function 2: Data source invocation

1. Function 2: Function response mapping template

1. Pipeline resolver **After** mapping template

**Note**  
Pipeline resolver execution flow is unidirectional and defined statically on the resolver.

#### Useful Apache Velocity Template Language (VTL) utilities
<a name="useful-apache-velocity-template-language-vtl-utilities"></a>

As the complexity of an application increases, VTL utilities and directives are here to facilitate development productivity. The following utilities can help you when you’re working with pipeline resolvers.

##### \$1ctx.stash
<a name="ctx-stash"></a>

The stash is a `Map` that is made available inside each resolver and function mapping template. The same stash instance lives through a single resolver execution. What this means is you can use the stash to pass arbitrary data across request and response mapping templates, and across functions in a pipeline resolver. The stash exposes the same methods as the [Java map](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html) data structure.

##### \$1ctx.prev.result
<a name="ctx-prev-result"></a>

The `$ctx.prev.result` represents the result of the previous operation that was executed in the pipeline resolver.

If the previous operation was the pipeline resolver's Before mapping template, then `$ctx.prev.result` represents the output of the evaluation of the template and is made available to the first function in the pipeline. If the previous operation was the first function, then `$ctx.prev.result` represents the output of the first function and is made available to the second function in the pipeline. If the previous operation was the last function, then `$ctx.prev.result` represents the output of the last function and is made available to the pipeline resolver's After mapping template.

##### \$1return(data: Object)
<a name="return-data-object"></a>

The `#return(data: Object)` directive comes handy if you need to return prematurely from any mapping template. `#return(data: Object)` is analogous to the *return* keyword in programming languages because it returns from the closest scoped block of logic. What this means is that using `#return` inside a resolver mapping template returns from the resolver. Using `#return(data: Object)` in a resolver mapping template sets `data` on the GraphQL field. Additionally, using `#return(data: Object)` from a function mapping template returns from the function and continues the execution to either the next function in the pipeline or the resolver response mapping template.

##### \$1return
<a name="return"></a>

This is the same as `#return(data: Object)`, but `null` will be returned instead.

##### \$1util.error
<a name="util-error"></a>

The `$util.error` utility is useful to throw a field error. Using `$util.error` inside a function mapping template throws a field error immediately, which prevents subsequent functions from being executed. For more details and other `$util.error` signatures, visit the [Resolver mapping template utility reference](resolver-util-reference.md#aws-appsync-resolver-mapping-template-util-reference).

##### \$1util.appendError
<a name="util-appenderror"></a>

The `$util.appendError` is similar to the `$util.error()`, with the major distinction that it doesn’t interrupt the evaluation of the mapping template. Instead, it signals there was an error with the field, but allows the template to be evaluated and consequently return data. Using `$util.appendError` inside a function will not disrupt the execution flow of the pipeline. For more details and other `$util.error` signatures, visit the [Resolver mapping template utility reference](resolver-util-reference.md#aws-appsync-resolver-mapping-template-util-reference).

## Example template
<a name="example-template"></a>

Suppose you have a DynamoDB data source and a **Unit** resolver on a field named `getPost(id:ID!)` that returns a `Post` type with the following GraphQL query:

```
getPost(id:1){
    id
    title
    content
}
```

Your resolver template might look like the following:

```
{
    "version" : "2018-05-29",
    "operation" : "GetItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    }
}
```

This would substitute the `id` input parameter value of `1` for `${ctx.args.id}` and generate the following JSON:

```
{
    "version" : "2018-05-29",
    "operation" : "GetItem",
    "key" : {
        "id" : { "S" : "1" }
    }
}
```

AWS AppSync uses this template to generate instructions for communicating with DynamoDB and getting data (or performing other operations as appropriate). After the data returns, AWS AppSync runs it through an optional response mapping template, which you can use to perform data shaping or logic. For example, when we get the results back from DynamoDB, they might look like this:

```
{
        "id" : 1,
        "theTitle" : "AWS AppSync works offline!",
        "theContent-part1" : "It also has realtime functionality",
        "theContent-part2" : "using GraphQL"
}
```

You could choose to join two of the fields into a single field with the following response mapping template:

```
{
        "id" : $util.toJson($context.data.id),
        "title" : $util.toJson($context.data.theTitle),
        "content" : $util.toJson("${context.data.theContent-part1} ${context.data.theContent-part2}")
}
```

Here’s how the data is shaped after the template is applied to the data:

```
{
        "id" : 1,
        "title" : "AWS AppSync works offline!",
        "content" : "It also has realtime functionality using GraphQL"
}
```

This data is given back as the response to a client as follows:

```
{
        "data": {
                "getPost":      {
                        "id" : 1,
                        "title" : "AWS AppSync works offline!",
                        "content" : "It also has realtime functionality using GraphQL"
                }
        }
}
```

Note that under most circumstances, response mapping templates are a simple passthrough of data, differing mostly if you are returning an individual item or a list of items. For an individual item the passthrough is:

```
$util.toJson($context.result)
```

For lists the passthrough is usually:

```
$util.toJson($context.result.items)
```

To see more examples of both unit and pipeline resolvers, see [Resolver tutorials](tutorials.md#aws-appsync-tutorials).

## Evaluated mapping template deserialization rules
<a name="evaluated-mapping-template-deserialization-rules"></a>

Mapping templates evaluate to a string. In AWS AppSync, the output string must follow a JSON structure to be valid.

Additionally, the following deserialization rules are enforced.

### Duplicate keys are not allowed in JSON objects
<a name="duplicate-keys-are-not-allowed-in-json-objects"></a>

If the evaluated mapping template string represents a JSON object or contains an object that has duplicate keys, the mapping template returns the following error message:

 `Duplicate field 'aField' detected on Object. Duplicate JSON keys are not allowed.` 

Example of a duplicate key in an evaluated request mapping template:

```
{
    "version": "2018-05-29",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "postId": "1",
        "field": "getPost" ## key 'field' has been redefined
    }
}
```

To fix this error, do not redefine keys in JSON objects.

### Trailing characters are not allowed in JSON objects
<a name="trailing-characters-are-not-allowed-in-json-objects"></a>

If the evaluated mapping template string represents a JSON object and contains trailing extraneous characters, the mapping template returns the following error message:

 `Trailing characters at the end of the JSON string are not allowed.` 

Example of trailing characters in an evaluated request mapping template:

```
{
    "version": "2018-05-29",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "postId": "1",
    }
}extraneouschars
```

To fix this error, ensure that evaluated templates strictly evaluate to JSON.

# AWS AppSync resolver mapping template programming guide
<a name="resolver-mapping-template-reference-programming-guide"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

This is a cookbook-style tutorial of programming with the Apache Velocity Template Language (VTL) in AWS AppSync. If you are familiar with other programming languages such as JavaScript, C, or Java, it should be fairly straightforward.

AWS AppSync uses VTL to translate GraphQL requests from clients into a request to your data source. Then it reverses the process to translate the data source response back into a GraphQL response. VTL is a logical template language that gives you the power to manipulate both the request and the response in the standard request/response flow of a web application, using techniques such as:
+ Default values for new items
+ Input validation and formatting
+ Transforming and shaping data
+ Iterating over lists, maps, and arrays to pluck out or alter values
+ Filter/change responses based on user identity
+ Complex authorization checks

For example, you might want to perform a phone number validation in the service on a GraphQL argument, or convert an input parameter to upper case before storing it in DynamoDB. Or maybe you want client systems to provide a code, as part of a GraphQL argument, JWT token claim, or HTTP header, and only respond with data if the code matches a specific string in a list. These are all logical checks you can perform with VTL in AWS AppSync.

VTL allows you to apply logic using programming techniques that might be familiar. However, it is bounded to run within the standard request/response flow to ensure that your GraphQL API is scalable as your user base grows. Because AWS AppSync also supports AWS Lambda as a resolver, you can write Lambda functions in your programming language of choice (Node.js, Python, Go, Java, etc.) if you need more flexibility.

## Setup
<a name="setup"></a>

A common technique when learning a language is to print out results (for example, `console.log(variable)` in JavaScript) to see what happens. In this tutorial, we demonstrate this by creating a simple GraphQL schema and passing a map of values to a Lambda function. The Lambda function prints out the values and then responds with them. This will enable you to understand the request/response flow and see different programming techniques.

Start by creating the following GraphQL schema:

```
type Query {
    get(id: ID, meta: String): Thing
}

type Thing {
    id: ID!
    title: String!
    meta: String
}

schema {
    query: Query
}
```

Now create the following AWS Lambda function, using Node.js as the language:

```
exports.handler = (event, context, callback) => {
    console.log('VTL details: ', event);
    callback(null, event);
};
```

In the **Data Sources** pane of the AWS AppSync console, add this Lambda function as a new data source. Navigate back to the **Schema** page of the console and click the **ATTACH** button on the right, next to the `get(...):Thing` query. For the request template, choose the existing template from the **Invoke and forward arguments** menu. For the response template, choose **Return Lambda result**.

Open Amazon CloudWatch Logs for your Lambda function in one location, and from the **Queries** tab of the AWS AppSync console, run the following GraphQL query:

```
query test {
  get(id:123 meta:"testing"){
    id
    meta
  }
}
```

The GraphQL response should contain `id:123` and `meta:testing`, because the Lambda function is echoing them back. After a few seconds, you should see a record in CloudWatch Logs with these details as well.

## Variables
<a name="variables"></a>

VTL uses [references](https://velocity.apache.org/engine/1.7/user-guide.html#references), which you can use to store or manipulate data. There are three types of references in VTL: variables, properties, and methods. Variables have a `$` sign in front of them and are created with the `#set` directive:

```
#set($var = "a string")
```

Variables store similar types that you’re familiar with from other languages, such as numbers, strings, arrays, lists, and maps. You might have noticed a JSON payload being sent in the default request template for Lambda resolvers:

```
"payload": $util.toJson($context.arguments)
```

A couple of things to notice here - first, AWS AppSync provides several convenience functions for common operations. In this example, `$util.toJson` converts a variable to JSON. Second, the variable `$context.arguments` is automatically populated from a GraphQL request as a map object. You can create a new map as follows:

```
#set( $myMap = {
  "id": $context.arguments.id,
  "meta": "stuff",
  "upperMeta" : $context.arguments.meta.toUpperCase()
} )
```

You have now created a variable named `$myMap`, which has keys of `id`, `meta`, and `upperMeta`. This also demonstrates a few things:
+  `id` is populated with a key from the GraphQL arguments. This is common in VTL to grab arguments from clients.
+  `meta` is hardcoded with a value, showcasing default values.
+  `upperMeta` is transforming the `meta` argument using a method `.toUpperCase()`.

Put the previous code at the top of your request template and change the `payload` to use the new `$myMap` variable:

```
"payload": $util.toJson($myMap)
```

Run your Lambda function, and you can see the response change as well as this data in CloudWatch logs. As you walk through the rest of this tutorial, we will keep populating `$myMap` so you can run similar tests.

You can also set *properties\$1* on your variables. These could be simple strings, arrays, or JSON:

```
#set($myMap.myProperty = "ABC")
#set($myMap.arrProperty = ["Write", "Some", "GraphQL"])
#set($myMap.jsonProperty = {
    "AppSync" : "Offline and Realtime",
    "Cognito" : "AuthN and AuthZ"
})
```

### Quiet references
<a name="quiet-references"></a>

Because VTL is a templating language, by default, every reference you give it will do a `.toString()`. If the reference is undefined, it prints the actual reference representation, as a string. For example:

```
#set($myValue = 5)
##Prints '5'
$myValue

##Prints '$somethingelse'
$somethingelse
```

To address this, VTL has a *quiet reference* or *silent reference* syntax, which tells the template engine to suppress this behavior. The syntax for this is `$!{}`. For example, if we changed the previous code slightly to use `$!{somethingelse}`, the printing is suppressed:

```
#set($myValue = 5)
##Prints '5'
$myValue

##Nothing prints out
$!{somethingelse}
```

## Calling methods
<a name="calling-methods"></a>

In an earlier example, we showed you how to create a variable and simultaneously set values. You can also do this in two steps by adding data to your map as shown following:

```
#set ($myMap = {})
#set ($myList = [])

##Nothing prints out
$!{myMap.put("id", "first value")}
##Prints "first value"
$!{myMap.put("id", "another value")}
##Prints true
$!{myList.add("something")}
```

 **HOWEVER** there is something to know about this behavior. Although the quiet reference notation `$!{}` allows you to call methods, as above, it won’t suppress the returned value of the executed method. This is why we noted `##Prints "first value"` and `##Prints true` above. This can cause errors when you’re iterating over maps or lists, such as inserting a value where a key already exists, because the output adds unexpected strings to the template upon evaluation.

The workaround to this is sometimes to call the methods using a `#set` directive and ignore the variable. For example:

```
#set ($myMap = {})
#set($discard = $myMap.put("id", "first value"))
```

You might use this technique in your templates, as it prevents the unexpected strings from being printed in the template. AWS AppSync provides an alternative convenience function that offers the same behavior in a more succinct notation. This enables you to not have to think about these implementation specifics. You can access this function under `$util.quiet()` or its alias `$util.qr()`. For example:

```
#set ($myMap = {})
#set ($myList = [])

##Nothing prints out
$util.quiet($myMap.put("id", "first value"))
##Nothing prints out
$util.qr($myList.add("something"))
```

## Strings
<a name="strings"></a>

As with many programming languages, strings can be difficult to deal with, especially when you want to build them from variables. There are some common things that come up with VTL.

Suppose you are inserting data as a string to a data source like DynamoDB, but it is populated from a variable, like a GraphQL argument. A string will have double quotation marks, and to reference the variable in a string you just need `"${}"` (so no `!` as in [quiet reference notation](https://velocity.apache.org/engine/1.7/user-guide.html#quiet-reference-notation)). This is similar to a template literal in JavaScript: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template\$1literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) 

```
#set($firstname = "Jeff")
$!{myMap.put("Firstname", "${firstname}")}
```

You can see this in DynamoDB request templates, like `"author": { "S" : "${context.arguments.author}"}` when using arguments from GraphQL clients, or for automatic ID generation like `"id" : { "S" : "$util.autoId()"}`. This means that you can reference a variable or the result of a method inside a string to populate data.

You can also use public methods of the Java [String class](https://docs.oracle.com/javase/6/docs/api/java/lang/String.html), such as pulling out a substring:

```
#set($bigstring = "This is a long string, I want to pull out everything after the comma")
#set ($comma = $bigstring.indexOf(','))
#set ($comma = $comma +2)
#set ($substring = $bigstring.substring($comma))

$util.qr($myMap.put("substring", "${substring}"))
```

String concatenation is also a very common task. You can do this with variable references alone or with static values:

```
#set($s1 = "Hello")
#set($s2 = " World")

$util.qr($myMap.put("concat","$s1$s2"))
$util.qr($myMap.put("concat2","Second $s1 World"))
```

## Loops
<a name="loops"></a>

Now that you have created variables and called methods, you can add some logic to your code. Unlike other languages, VTL allows only loops, where the number of iterations is predetermined. There is no `do..while` in Velocity. This design ensures that the evaluation process always terminates, and provides bounds for scalability when your GraphQL operations execute.

Loops are created with a `#foreach` and require you to supply a **loop variable** and an **iterable object** such as an array, list, map, or collection. A classic programming example with a `#foreach` loop is to loop over the items in a collection and print them out, so in our case we pluck them out and add them to the map:

```
#set($start = 0)
#set($end = 5)
#set($range = [$start..$end])

#foreach($i in $range)
   ##$util.qr($myMap.put($i, "abc"))
   ##$util.qr($myMap.put($i, $i.toString()+"foo")) ##Concat variable with string
   $util.qr($myMap.put($i, "${i}foo"))     ##Reference a variable in a string with "${varname}"
#end
```

This example shows a few things. The first is using variables with the range `[..]` operator to create an iterable object. Then each item is referenced by a variable `$i` that you can operate with. In the previous example, you also see **Comments** that are denoted with a double pound `##`. This also showcases using the loop variable in both the keys or the values, as well as different methods of concatenation using strings.

Notice that `$i` is an integer, so you can call a `.toString()` method. For GraphQL types of INT, this can be handy.

You can also use a range operator directly, for example:

```
#foreach($item in [1..5])
    ...
#end
```

## Arrays
<a name="arrays"></a>

You have been manipulating a map up to this point, but arrays are also common in VTL. With arrays you also have access to some underlying methods such as `.isEmpty()`, `.size()`, `.set()`, `.get()`, and `.add()`, as shown below:

```
#set($array = [])
#set($idx = 0)

##adding elements
$util.qr($array.add("element in array"))
$util.qr($myMap.put("array", $array[$idx]))

##initialize array vals on create
#set($arr2 = [42, "a string", 21, "test"])

$util.qr($myMap.put("arr2", $arr2[$idx]))
$util.qr($myMap.put("isEmpty", $array.isEmpty()))  ##isEmpty == false
$util.qr($myMap.put("size", $array.size()))

##Get and set items in an array
$util.qr($myMap.put("set", $array.set(0, 'changing array value')))
$util.qr($myMap.put("get", $array.get(0)))
```

The previous example used array index notation to retrieve an element with `arr2[$idx]`. You can look up by name from a Map/dictionary in a similar way:

```
#set($result = {
    "Author" : "Nadia",
    "Topic" : "GraphQL"
})

$util.qr($myMap.put("Author", $result["Author"]))
```

This is very common when filtering results coming back from data sources in Response Templates when using conditionals.

## Conditional checks
<a name="conditional-checks"></a>

The earlier section with `#foreach` showcased some examples of using logic to transform data with VTL. You can also apply conditional checks to evaluate data at runtime:

```
#if(!$array.isEmpty())
    $util.qr($myMap.put("ifCheck", "Array not empty"))
#else
    $util.qr($myMap.put("ifCheck", "Your array is empty"))
#end
```

The above `#if()` check of a Boolean expression is nice, but you can also use operators and `#elseif()` for branching:

```
#if ($arr2.size() == 0)
    $util.qr($myMap.put("elseIfCheck", "You forgot to put anything into this array!"))
#elseif ($arr2.size() == 1)
    $util.qr($myMap.put("elseIfCheck", "Good start but please add more stuff"))
#else
    $util.qr($myMap.put("elseIfCheck", "Good job!"))
#end
```

These two examples showed negation(\$1) and equality (==). We can also use \$1\$1, &&, >, <, >=, <=, and \$1=.

```
#set($T = true)
#set($F = false)

#if ($T || $F)
  $util.qr($myMap.put("OR", "TRUE"))
#end

#if ($T && $F)
  $util.qr($myMap.put("AND", "TRUE"))
#end
```

 **Note:** Only `Boolean.FALSE` and `null` are considered false in conditionals. Zero (0) and empty strings (“”) are not equivalent to false.

## Operators
<a name="operators"></a>

No programming language would be complete without some operators to perform some mathematical actions. Here are a few examples to get you started:

```
#set($x = 5)
#set($y = 7)
#set($z = $x + $y)
#set($x-y = $x - $y)
#set($xy = $x * $y)
#set($xDIVy = $x / $y)
#set($xMODy = $x % $y)

$util.qr($myMap.put("z", $z))
$util.qr($myMap.put("x-y", $x-y))
$util.qr($myMap.put("x*y", $xy))
$util.qr($myMap.put("x/y", $xDIVy))
$util.qr($myMap.put("x|y", $xMODy))
```

### Using loops and conditionals together
<a name="loops-and-conditionals-together"></a>

It is very common when transforming data in VTL, such as before writing or reading from a data source, to loop over objects and then perform checks before performing an action. Combining some of the tools from the previous sections gives you a lot of functionality. One handy tool is knowing that `#foreach` automatically provides you with a `.count` on each item:

```
#foreach ($item in $arr2)
  #set($idx = "item" + $foreach.count)
  $util.qr($myMap.put($idx, $item))
#end
```

For example, maybe you want to just pluck out values from a map if it is under a certain size. Using the count along with conditionals and the `#break` statement allows you to do this:

```
#set($hashmap = {
  "DynamoDB" : "https://aws.amazon.com/dynamodb/",
  "Amplify" : "https://github.com/aws/aws-amplify",
  "DynamoDB2" : "https://aws.amazon.com/dynamodb/",
  "Amplify2" : "https://github.com/aws/aws-amplify"
})

#foreach ($key in $hashmap.keySet())
    #if($foreach.count > 2)
    #break
  #end
    $util.qr($myMap.put($key, $hashmap.get($key)))
#end
```

The previous `#foreach` is iterated over with `.keySet()`, which you can use on maps. This gives you access to get the `$key` and reference the value with a `.get($key)`. GraphQL arguments from clients in AWS AppSync are stored as a map. They can also be iterated through with `.entrySet()`, which you can then access both keys and values as a Set, and either populate other variables or perform complex conditional checks, such as validation or transformation of input:

```
#foreach( $entry in $context.arguments.entrySet() )
#if ($entry.key == "XYZ" && $entry.value == "BAD")
    #set($myvar = "...")
  #else
    #break
  #end
#end
```

Other common examples are automatically populating default information, like the initial object versions when synchronizing data (very important in conflict resolution) or the default owner of an object for authorization checks - Mary created this blog post, so:

```
#set($myMap.owner ="Mary")
#set($myMap.defaultOwners = ["Admins", "Editors"])
```

## Context
<a name="context"></a>

Now that you are more familiar with performing logical checks in AWS AppSync resolvers with VTL, take a look at the context object:

```
$util.qr($myMap.put("context", $context))
```

This contains all of the information that you can access in your GraphQL request. For a detailed explanation, see the [context reference](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference).

## Filtering
<a name="filtering"></a>

So far in this tutorial all information from your Lambda function has been returned to the GraphQL query with a very simple JSON transformation:

```
$util.toJson($context.result)
```

The VTL logic is just as powerful when you get responses from a data source, especially when doing authorization checks on resources. Let’s walk through some examples. First try changing your response template like so:

```
#set($data = {
    "id" : "456",
    "meta" : "Valid Response"
})

$util.toJson($data)
```

No matter what happens with your GraphQL operation, hardcoded values are returned back to the client. Change this slightly so that the `meta` field is populated from the Lambda response, set earlier in the tutorial in the `elseIfCheck` value when learning about conditionals:

```
#set($data = {
    "id" : "456"
})

#foreach($item in $context.result.entrySet())
    #if($item.key == "elseIfCheck")
        $util.qr($data.put("meta", $item.value))
    #end
#end

$util.toJson($data)
```

 `$context.result` is a map, so you can use `entrySet()` to perform logic on either the keys or the values returned. Because `$context.identity` contains information on the user that performed the GraphQL operation, if you return authorization information from the data source, then you can decide to return all, partial, or no data to a user based on your logic. Change your response template to look like the following:

```
#if($context.result["id"] == 123)
    $util.toJson($context.result)
  #else
    $util.unauthorized()
#end
```

If you run your GraphQL query, the data will be returned as normal. However, if you change the id argument to something other than 123 (`query test { get(id:456 meta:"badrequest"){} }`), you will get an authorization failure message.

You can find more examples of authorization scenarios in the [authorization use cases](security-authorization-use-cases.md#aws-appsync-security-authorization-use-cases) section.

### Template sample
<a name="appendix-template-sample"></a>

If you followed along with the tutorial, you may have built out this template step by step. In case you haven’t, we include it below to copy for testing.

 **Request Template** 

```
#set( $myMap = {
  "id": $context.arguments.id,
  "meta": "stuff",
  "upperMeta" : "$context.arguments.meta.toUpperCase()"
} )

##This is how you would do it in two steps with a "quiet reference" and you can use it for invoking methods, such as .put() to add items to a Map
#set ($myMap2 = {})
$util.qr($myMap2.put("id", "first value"))

## Properties are created with a dot notation
#set($myMap.myProperty = "ABC")
#set($myMap.arrProperty = ["Write", "Some", "GraphQL"])
#set($myMap.jsonProperty = {
    "AppSync" : "Offline and Realtime",
    "Cognito" : "AuthN and AuthZ"
})

##When you are inside a string and just have ${} without ! it means stuff inside curly braces are a reference
#set($firstname = "Jeff")
$util.qr($myMap.put("Firstname", "${firstname}"))

#set($bigstring = "This is a long string, I want to pull out everything after the comma")
#set ($comma = $bigstring.indexOf(','))
#set ($comma = $comma +2)
#set ($substring = $bigstring.substring($comma))
$util.qr($myMap.put("substring", "${substring}"))

##Classic for-each loop over N items:
#set($start = 0)
#set($end = 5)
#set($range = [$start..$end])
#foreach($i in $range)          ##Can also use range operator directly like #foreach($item in [1...5])
   ##$util.qr($myMap.put($i, "abc"))
   ##$util.qr($myMap.put($i, $i.toString()+"foo")) ##Concat variable with string
   $util.qr($myMap.put($i, "${i}foo"))     ##Reference a variable in a string with "${varname)"
#end

##Operators don't work
#set($x = 5)
#set($y = 7)
#set($z = $x + $y)
#set($x-y = $x - $y)
#set($xy = $x * $y)
#set($xDIVy = $x / $y)
#set($xMODy = $x % $y)
$util.qr($myMap.put("z", $z))
$util.qr($myMap.put("x-y", $x-y))
$util.qr($myMap.put("x*y", $xy))
$util.qr($myMap.put("x/y", $xDIVy))
$util.qr($myMap.put("x|y", $xMODy))

##arrays
#set($array = ["first"])
#set($idx = 0)
$util.qr($myMap.put("array", $array[$idx]))
##initialize array vals on create
#set($arr2 = [42, "a string", 21, "test"])
$util.qr($myMap.put("arr2", $arr2[$idx]))
$util.qr($myMap.put("isEmpty", $array.isEmpty()))  ##Returns false
$util.qr($myMap.put("size", $array.size()))
##Get and set items in an array
$util.qr($myMap.put("set", $array.set(0, 'changing array value')))
$util.qr($myMap.put("get", $array.get(0)))

##Lookup by name from a Map/dictionary in a similar way:
#set($result = {
    "Author" : "Nadia",
    "Topic" : "GraphQL"
})
$util.qr($myMap.put("Author", $result["Author"]))


##Conditional examples
#if(!$array.isEmpty())
$util.qr($myMap.put("ifCheck", "Array not empty"))
#else
$util.qr($myMap.put("ifCheck", "Your array is empty"))
#end

#if ($arr2.size() == 0)
$util.qr($myMap.put("elseIfCheck", "You forgot to put anything into this array!"))
#elseif ($arr2.size() == 1)
$util.qr($myMap.put("elseIfCheck", "Good start but please add more stuff"))
#else
$util.qr($myMap.put("elseIfCheck", "Good job!"))
#end

##Above showed negation(!) and equality (==), we can also use OR, AND, >, <, >=, <=, and !=
#set($T = true)
#set($F = false)
#if ($T || $F)
  $util.qr($myMap.put("OR", "TRUE"))
#end

#if ($T && $F)
  $util.qr($myMap.put("AND", "TRUE"))
#end

##Using the foreach loop counter - $foreach.count
#foreach ($item in $arr2)
  #set($idx = "item" + $foreach.count)
  $util.qr($myMap.put($idx, $item))
#end

##Using a Map and plucking out keys/vals
#set($hashmap = {
    "DynamoDB" : "https://aws.amazon.com/dynamodb/",
    "Amplify" : "https://github.com/aws/aws-amplify",
    "DynamoDB2" : "https://aws.amazon.com/dynamodb/",
    "Amplify2" : "https://github.com/aws/aws-amplify"
})

#foreach ($key in $hashmap.keySet())
    #if($foreach.count > 2)
        #break
    #end
    $util.qr($myMap.put($key, $hashmap.get($key)))
#end

##concatenate strings
#set($s1 = "Hello")
#set($s2 = " World")
$util.qr($myMap.put("concat","$s1$s2"))
$util.qr($myMap.put("concat2","Second $s1 World"))

$util.qr($myMap.put("context", $context))

{
    "version" : "2017-02-28",
    "operation": "Invoke",
    "payload": $util.toJson($myMap)
}
```

 **Response Template** 

```
#set($data = {
"id" : "456"
})
#foreach($item in $context.result.entrySet())   ##$context.result is a MAP so we use entrySet()
    #if($item.key == "ifCheck")
        $util.qr($data.put("meta", "$item.value"))
    #end
#end

##Uncomment this out if you want to test and remove the below #if check
##$util.toJson($data)

#if($context.result["id"] == 123)
    $util.toJson($context.result)
  #else
    $util.unauthorized()
#end
```

# AWS AppSync resolver mapping template context reference
<a name="resolver-context-reference"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

AWS AppSync defines a set of variables and functions for working with resolver mapping templates. This makes logical operations on data easier with GraphQL. This document describes those functions and provides examples for working with templates.

## Accessing the `$context`
<a name="accessing-the-context"></a>

The `$context` variable is a map that holds all of the contextual information for your resolver invocation. It has the following structure:

```
{
   "arguments" : { ... },
   "source" : { ... },
   "result" : { ... },
   "identity" : { ... },
   "request" : { ... },
   "info": { ... }
}
```

**Note**  
If you're trying to access a dictionary/map entry (such as an entry in `context`) by its key to retrieve the value, the Velocity Template Language (VTL) lets you directly use the notation `<dictionary-element>.<key-name>`. However, this might not work for all cases, such as when the key names have special characters (for example, an underscore "\$1"). We recommend that you always use `<dictionary-element>.get("<key-name>")` notation.

Each field in the `$context` map is defined as follows:

### `$context` fields
<a name="accessing-the-context-list"></a>

** `arguments` **  
A map that contains all GraphQL arguments for this field.

** `identity` **  
An object that contains information about the caller. For more information about the structure of this field, see [Identity](#aws-appsync-resolver-context-reference-identity).

** `source` **  
A map that contains the resolution of the parent field.

** `stash` **  
The stash is a map that is made available inside each resolver and function mapping template. The same stash instance lives through a single resolver execution. This means that you can use the stash to pass arbitrary data across request and response mapping templates, and across functions in a pipeline resolver. The stash exposes the same methods as the [Java Map](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html) data structure.

** `result` **  
A container for the results of this resolver. This field is available only to response mapping templates.  
For example, if you're resolving the `author` field of the following query:  

```
query {
    getPost(id: 1234) {
        postId
        title
        content
        author {
            id
            name
        }
    }
}
```
Then the full `$context` variable that is available when processing a response mapping template might be:  

```
{
  "arguments" : {
    id: "1234"
  },
  "source": {},
  "result" : {
      "postId": "1234",
      "title": "Some title",
      "content": "Some content",
      "author": {
        "id": "5678",
        "name": "Author Name"
      }
  },
  "identity" : {
      "sourceIp" : ["x.x.x.x"],
      "userArn" : "arn:aws:iam::123456789012:user/appsync",
      "accountId" : "666666666666",
      "user" : "AIDAAAAAAAAAAAAAAAAAA"
  }
}
```

** `prev.result` **  
The result of whatever previous operation was executed in a pipeline resolver.  
If the previous operation was the pipeline resolver's Before mapping template, then `$ctx.prev.result` represents the output of the evaluation of the template and is made available to the first function in the pipeline.  
If the previous operation was the first function, then `$ctx.prev.result` represents the output of the first function and is made available to the second function in the pipeline.  
If the previous operation was the last function, then `$ctx.prev.result` represents the output of the last function and is made available to the pipeline resolver's After mapping template.

** `info` **  
An object that contains information about the GraphQL request. For the structure of this field, see [Info](#aws-appsync-resolver-context-reference-info).

### Identity
<a name="aws-appsync-resolver-context-reference-identity"></a>

The `identity` section contains information about the caller. The shape of this section depends on the authorization type of your AWS AppSync API.

For more information about AWS AppSync security options, see [Authorization and authentication](security-authz.md#aws-appsync-security).

** `API_KEY` authorization**  
The `identity` field isn't populated.

**`AWS_LAMBDA` authorization**  
The `identity` contains the `resolverContext` key, containing the same `resolverContext` content returned by the Lambda function authorizing the request.

** `AWS_IAM` authorization**  
The `identity` has the following form:  

```
{
    "accountId" : "string",
    "cognitoIdentityPoolId" : "string",
    "cognitoIdentityId" : "string",
    "sourceIp" : ["string"],
    "username" : "string", // IAM user principal
    "userArn" : "string",
    "cognitoIdentityAuthType" : "string", // authenticated/unauthenticated based on the identity type
    "cognitoIdentityAuthProvider" : "string" // the auth provider that was used to obtain the credentials
}
```

** `AMAZON_COGNITO_USER_POOLS` authorization**  
The `identity` has the following form:  

```
{
    "sub" : "uuid",
    "issuer" : "string",
    "username" : "string"
    "claims" : { ... },
    "sourceIp" : ["x.x.x.x"],
    "defaultAuthStrategy" : "string"
}
```

Each field is defined as follows:

** `accountId` **  
The AWS account ID of the caller.

** `claims` **  
The claims that the user has.

** `cognitoIdentityAuthType` **  
Either authenticated or unauthenticated based on the identity type.

** `cognitoIdentityAuthProvider` **  
A comma-separated list of external identity provider information used in obtaining the credentials used to sign the request.

** `cognitoIdentityId` **  
The Amazon Cognito identity ID of the caller.

** `cognitoIdentityPoolId` **  
The Amazon Cognito identity pool ID associated with the caller.

** `defaultAuthStrategy` **  
The default authorization strategy for this caller (`ALLOW` or `DENY`).

** `issuer` **  
The token issuer.

** `sourceIp` **  
The source IP address of the caller that AWS AppSync receives. If the request doesn't include the `x-forwarded-for` header, the source IP value contains only a single IP address from the TCP connection. If the request includes a `x-forwarded-for` header, the source IP is a list of IP addresses from the `x-forwarded-for` header, in addition to the IP address from the TCP connection.

** `sub` **  
The UUID of the authenticated user.

** `user` **  
The IAM user.

** `userArn` **  
The Amazon Resource Name (ARN) of the IAM user.

** `username` **  
The user name of the authenticated user. In the case of `AMAZON_COGNITO_USER_POOLS` authorization, the value of *username* is the value of attribute *cognito:username*. In the case of `AWS_IAM` authorization, the value of *username* is the value of the AWS user principal. If you're using IAM authorization with credentials vended from Amazon Cognito identity pools, we recommend that you use `cognitoIdentityId`.

### Access request headers
<a name="aws-appsync-resolver-context-reference-util"></a>

AWS AppSync supports passing custom headers from clients and accessing them in your GraphQL resolvers by using `$context.request.headers`. You can then use the header values for actions such as inserting data into a data source or authorization checks. You can use single or multiple request headers using `$curl` with an API key from the command line, as shown in the following examples:

**Single header example** 

Suppose you set a header of `custom` with a value of `nadia` like the following:

```
curl -XPOST -H "Content-Type:application/graphql" -H "custom:nadia" -H "x-api-key:<API-KEY-VALUE>" -d '{"query":"mutation { createEvent(name: \"demo\", when: \"Next Friday!\", where: \"Here!\") {id name when where description}}"}' https://<ENDPOINT>/graphql
```

This could then be accessed with `$context.request.headers.custom`. For example, it might be in the following VTL for DynamoDB:

```
"custom": $util.dynamodb.toDynamoDBJson($context.request.headers.custom)
```

**Multiple header example** 

You can also pass multiple headers in a single request and access these in the resolver mapping template. For example, if the `custom` header is set with two values:

```
curl -XPOST -H "Content-Type:application/graphql" -H "custom:bailey" -H "custom:nadia" -H "x-api-key:<API-KEY-VALUE>" -d '{"query":"mutation { createEvent(name: \"demo\", when: \"Next Friday!\", where: \"Here!\") {id name when where description}}"}' https://<ENDPOINT>/graphql
```

You could then access these as an array, such as `$context.request.headers.custom[1]`.

**Note**  
AWS AppSync doesn't expose the cookie header in `$context.request.headers`.

### Access the request custom domain name
<a name="aws-access-requested-custom-domain-names"></a>

AWS AppSync supports configuring a custom domain that you can use to access your GraphQL and real-time endpoints for your APIs. When making a request with a custom domain name, you can get the domain name using `$context.request.domainName`.

When using the default GraphQL endpoint domain name, the value is `null`.

### Info
<a name="aws-appsync-resolver-context-reference-info"></a>

The `info` section contains information about the GraphQL request. This section has the following form:

```
{
    "fieldName": "string",
    "parentTypeName": "string",
    "variables": { ... },
    "selectionSetList": ["string"],
    "selectionSetGraphQL": "string"
}
```

Each field is defined as follows:

** `fieldName` **  
The name of the field that is currently being resolved.

** `parentTypeName` **  
The name of the parent type for the field that is currently being resolved.

** `variables` **  
A map which holds all variables that are passed into the GraphQL request.

** `selectionSetList` **  
A list representation of the fields in the GraphQL selection set. Fields that are aliased are referenced only by the alias name, not the field name. The following example shows this in detail.

** `selectionSetGraphQL` **  
A string representation of the selection set, formatted as GraphQL schema definition language (SDL). Although fragments aren't merged into the selection set, inline fragments are preserved, as shown in the following example.

**Note**  
When using `$utils.toJson()` on `context.info`, the values that `selectionSetGraphQL` and `selectionSetList` return are not serialized by default.

For example, if you are resolving the `getPost` field of the following query:

```
query {
  getPost(id: $postId) {
    postId
    title
    secondTitle: title
    content
    author(id: $authorId) {
      authorId
      name
    }
    secondAuthor(id: "789") {
      authorId
    }
    ... on Post {
      inlineFrag: comments: {
        id
      }
    }
    ... postFrag
  }
}

fragment postFrag on Post {
  postFrag: comments: {
    id
  }
}
```

Then the full `$context.info` variable that is available when processing a mapping template might be:

```
{
  "fieldName": "getPost",
  "parentTypeName": "Query",
  "variables": {
    "postId": "123",
    "authorId": "456"
  },
  "selectionSetList": [
    "postId",
    "title",
    "secondTitle"
    "content",
    "author",
    "author/authorId",
    "author/name",
    "secondAuthor",
    "secondAuthor/authorId",
    "inlineFragComments",
    "inlineFragComments/id",
    "postFragComments",
    "postFragComments/id"
  ],
  "selectionSetGraphQL": "{\n  getPost(id: $postId) {\n    postId\n    title\n    secondTitle: title\n    content\n    author(id: $authorId) {\n      authorId\n      name\n    }\n    secondAuthor(id: \"789\") {\n      authorId\n    }\n    ... on Post {\n      inlineFrag: comments {\n        id\n      }\n    }\n    ... postFrag\n  }\n}"
}
```

`selectionSetList` exposes only fields that belong to the current type. If the current type is an interface or union, only selected fields that belong to the interface are exposed. For example, given the following schema:

```
type Query {
    node(id: ID!): Node
}

interface Node {
    id: ID
}

type Post implements Node {
    id: ID
    title: String
    author: String
}

type Blog implements Node {
    id: ID
    title: String
    category: String
}
```

And the following query:

```
query {
    node(id: "post1") {
        id
        ... on Post {
            title
        }

        ... on Blog {
            title
        }
    }
}
```

When calling `$ctx.info.selectionSetList` at the `Query.node` field resolution, only `id` is exposed:

```
"selectionSetList": [
    "id"
]
```

## Sanitizing inputs
<a name="sanitizing-inputs"></a>

Applications must sanitize untrusted inputs to prevent any external party from using an application outside of its intended use. As the `$context` contains user inputs in properties such as `$context.arguments`, `$context.identity`, `$context.result`, `$context.info.variables`, and `$context.request.headers`, care must be taken to sanitize their values in mapping templates.

Since mapping templates represent JSON, input sanitization takes the form of escaping JSON reserved characters from strings that represent user inputs. It is best practice to use the `$util.toJson()` utility to escape JSON reserved characters from sensitive string values when placing them into a mapping template.

For example, in the following Lambda request mapping template, because we accessed an unsafe customer input string (`$context.arguments.id`), we wrapped it with `$util.toJson()` to prevent unescaped JSON characters from breaking the JSON template.

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "postId": $util.toJson($context.arguments.id)
    }
}
```

As opposed to the mapping template below, where we directly insert `$context.arguments.id` without sanitization. This does not work for strings containing unescaped quotation marks or other JSON reserved characters, and can leave your template open to failure.

```
## DO NOT DO THIS
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "postId": "$context.arguments.id" ## Unsafe! Do not insert $context string values without escaping JSON characters.
    }
}
```

# AWS AppSync resolver mapping template utility reference
<a name="resolver-util-reference"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

AWS AppSync defines a set of utilities that you can use within a GraphQL resolver to simplify interactions with data sources. Some of these utilities are for general use with any data source, such as generating IDs or timestamps. Others are specific to a type of data source. The following utilities are available:
+  [ Utility helpers in \$1util ](https://docs.aws.amazon.com/appsync/latest/devguide/utility-helpers-in-util.html) - The \$1util variable contains general utility methods to help you work with data. Unless otherwise specified, all utilities use the UTF-8 character set.
+ [ AppSync directives](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-directives.html) - AppSync exposes directives to facilitate developer productivity when writing in VTL.
+  [ Time helpers in \$1util.time ](https://docs.aws.amazon.com/appsync/latest/devguide/time-helpers-in-util-time.html) - The \$1util.time variable contains datetime methods to help generate timestamps, convert between datetime formats, and parse datetime strings. The syntax for datetime formats is based on [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html), which you can reference for further documentation.
+ [ List helpers in \$1util.list ](https://docs.aws.amazon.com/appsync/latest/devguide/list-helpers-in-util-list.html) - \$1util.list contains methods to help with common List operations such as removing or retaining items from a list for filtering use cases.
+  [ Map helpers in \$1util.map ](https://docs.aws.amazon.com/appsync/latest/devguide/utility-helpers-in-map.html) - \$1util.map contains methods to help with common Map operations such as removing or retaining items from a Map for filtering use cases.
+  [ DynamoDB helpers in \$1util.dynamodb ](https://docs.aws.amazon.com/appsync/latest/devguide/dynamodb-helpers-in-util-dynamodb.html) - \$1util.dynamodb contains helper methods that make it easier to write and read data to Amazon DynamoDB, such as automatic type mapping and formatting. 
+  [ Amazon RDS helpers in \$1util.rds ](https://docs.aws.amazon.com/appsync/latest/devguide/rds-helpers-in-util-rds.html) - \$1util.rds contains helper methods that format RDS operations by getting rid of extraneous data in result outputs.
+  [ HTTP helpers in \$1util.http ](https://docs.aws.amazon.com/appsync/latest/devguide/http-helpers-in-utils-http.html) - The \$1util.http utility provides helper methods that you can use to manage HTTP request parameters and to add response headers.
+  [ XML helpers in \$1util.xml ](https://docs.aws.amazon.com/appsync/latest/devguide/xml-helpers-in-utils-xml.html) - \$1util.xml contains helper methods that can make it easier to translate XML responses to JSON or a Dictionary.
+  [ Transformation helpers in \$1util.transform ](https://docs.aws.amazon.com/appsync/latest/devguide/transformation-helpers-in-utils-transform.html) - \$1util.transform contains helper methods that make it easier to perform complex operations against data sources, such as DynamoDB filter operations.
+  [ Math helpers in \$1util.math ](https://docs.aws.amazon.com/appsync/latest/devguide/math-helpers-in-util-math.html) - \$1util.math contains methods to help with common Math operations.
+  [ String helpers in \$1util.str ](https://docs.aws.amazon.com/appsync/latest/devguide/str-helpers-in-util-str.html) - \$1util.str contains methods to help with common String operations.
+  [ Extensions ](https://docs.aws.amazon.com/appsync/latest/devguide/extensions.html) - \$1extensions contains a set of methods to make additional actions within your resolvers.

# Utility helpers in \$1util
<a name="utility-helpers-in-util"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The `$util` variable contains general utility methods to help you work with data. Unless otherwise specified, all utilities use the UTF-8 character set.

## JSON parsing utils
<a name="utility-helpers-in-json-parsing"></a>

### JSON parsing utils list
<a name="utility-helpers-in-json-parsing-list"></a>

** **`$util.parseJson(String) : Object`** **  
Takes "stringified" JSON and returns an object representation of the result.

** **`$util.toJson(Object) : String`** **  
Takes an object and returns a "stringified" JSON representation of that object.

## Encoding utils
<a name="utility-helpers-in-encoding"></a>

### Encoding utils list
<a name="utility-helpers-in-encoding-list"></a>

** **`$util.urlEncode(String) : String`** **  
Returns the input string as an `application/x-www-form-urlencoded` encoded string.

** **`$util.urlDecode(String) : String`** **  
Decodes an `application/x-www-form-urlencoded` encoded string back to its non-encoded form.

** **`$util.base64Encode( byte[] ) : String`** **  
Encodes the input into a base64-encoded string.

** **`$util.base64Decode(String) : byte[]`** **  
Decodes the data from a base64-encoded string.

## ID generation utils
<a name="utility-helpers-in-id-gen"></a>

### ID generation utils list
<a name="utility-helpers-in-id-gen-list"></a>

** **`$util.autoId() : String`** **  
Returns a 128-bit randomly generated UUID.

****`$util.autoUlid() : String`****  
Returns a 128-bit randomly generated ULID (Universally Unique Lexicographically Sortable Identifier).

****`$util.autoKsuid() : String`****  
Returns a 128-bit randomly generated KSUID (K-Sortable Unique Identifier) base62 encoded as a String with a length of 27.

## Error utils
<a name="utility-helpers-in-error"></a>

### Error utils list
<a name="utility-helpers-in-error-list"></a>

** `$util.error(String)` **  
Throws a custom error. Use this in request or response mapping templates to detect an error with the request or with the invocation result.

** `$util.error(String, String)` **  
Throws a custom error. Use this in request or response mapping templates to detect an error with the request or with the invocation result. You can also specify an `errorType`.

** `$util.error(String, String, Object)` **  
Throws a custom error. Use this in request or response mapping templates to detect an error with the request or with the invocation result. You can also specify an `errorType` and a `data` field. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.  
`data` will be filtered based on the query selection set.

** `$util.error(String, String, Object, Object)` **  
Throws a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` field, a `data` field, and an `errorInfo` field can be specified. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.   
`data` will be filtered based on the query selection set. The `errorInfo` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.  
`errorInfo` will **NOT** be filtered based on the query selection set.

** `$util.appendError(String)` **  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Unlike `$util.error(String)`, the template evaluation will not be interrupted, so that data can be returned to the caller.

** `$util.appendError(String, String)` **  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` can be specified. Unlike `$util.error(String, String)`, the template evaluation will not be interrupted, so that data can be returned to the caller.

** `$util.appendError(String, String, Object)` **  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` and a `data` field can be specified. Unlike `$util.error(String, String, Object)`, the template evaluation will not be interrupted, so that data can be returned to the caller. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.   
`data` will be filtered based on the query selection set.

** `$util.appendError(String, String, Object, Object)` **  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` field, a `data` field, and an `errorInfo` field can be specified. Unlike `$util.error(String, String, Object, Object)`, the template evaluation will not be interrupted, so that data can be returned to the caller. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.  
`data` will be filtered based on the query selection set. The `errorInfo` value will be added to the corresponding `error` block inside `errors` in the GraphQL response.  
`errorInfo` will **NOT** be filtered based on the query selection set.

## Condition validation utils
<a name="utility-helpers-in-condition"></a>

### Condition validation utils list
<a name="utility-helpers-in-condition-list"></a>

** `$util.validate(Boolean, String) : void` **  
If the condition is false, throw a CustomTemplateException with the specified message.

** `$util.validate(Boolean, String, String) : void` **  
If the condition is false, throw a CustomTemplateException with the specified message and error type.

** `$util.validate(Boolean, String, String, Object) : void` **  
If the condition is false, throw a CustomTemplateException with the specified message and error type, as well as data to return in the response.

## Null behavior utils
<a name="utility-helpers-in-null-behavior"></a>

### Null behavior utils list
<a name="utility-helpers-in-null-behavior-list"></a>

** `$util.isNull(Object) : Boolean` **  
Returns true if the supplied object is null.

** `$util.isNullOrEmpty(String) : Boolean` **  
Returns true if the supplied data is null or an empty string. Otherwise, returns false.

** `$util.isNullOrBlank(String) : Boolean` **  
Returns true if the supplied data is null or a blank string. Otherwise, returns false.

** `$util.defaultIfNull(Object, Object) : Object` **  
Returns the first Object if it is not null. Otherwise, returns second object as a "default Object".

** `$util.defaultIfNullOrEmpty(String, String) : String` **  
Returns the first String if it is not null or empty. Otherwise, returns second String as a "default String".

** `$util.defaultIfNullOrBlank(String, String) : String` **  
Returns the first String if it is not null or blank. Otherwise, returns second String as a "default String".

## Pattern matching utils
<a name="utility-helpers-in-pattern-matching"></a>

### Type and pattern matching utils list
<a name="utility-helpers-in-type-pattern-matching-list"></a>

** `$util.typeOf(Object) : String` **  
Returns a String describing the type of the Object. Supported type identifications are: "Null", "Number", "String", "Map", "List", "Boolean". If a type cannot be identified, the return type is "Object".

** `$util.matches(String, String) : Boolean` **  
Returns true if the specified pattern in the first argument matches the supplied data in the second argument. The pattern must be a regular expression such as `$util.matches("a*b", "aaaaab")`. The functionality is based on [Pattern](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html), which you can reference for further documentation.

** `$util.authType() : String` **  
Returns a String describing the multi-auth type being used by a request, returning back either "IAM Authorization", "User Pool Authorization", "Open ID Connect Authorization", or "API Key Authorization".

## Object validation utils
<a name="utility-helpers-in-object-validation"></a>

### Object validation utils list
<a name="utility-helpers-in-object-validation-list"></a>

** `$util.isString(Object) : Boolean` **  
Returns true if the Object is a String.

** `$util.isNumber(Object) : Boolean` **  
Returns true if the Object is a Number.

** `$util.isBoolean(Object) : Boolean` **  
Returns true if the Object is a Boolean.

** `$util.isList(Object) : Boolean` **  
Returns true if the Object is a List.

** `$util.isMap(Object) : Boolean` **  
Returns true if the Object is a Map.

## CloudWatch logging utils
<a name="utility-helpers-in-logging"></a>

### CloudWatch logging utils list
<a name="utility-helpers-in-cloudwatch-logs"></a>

**`$util.log.info(Object) : Void`**  
Logs the String representation of the provided Object to the requested log stream when request-level and field-level CloudWatch logging is enabled with log level `ALL`, `INFO`, or `DEBUG` on an API.

**`$util.log.info(String, Object...) : Void`**  
Logs the String representation of the provided Objects to the requested log stream when request-level and field-level CloudWatch logging is enabled with log level `ALL` on an API. This utility will replace all variables indicated by "\$1\$1" in the first input format String with the String representation of the provided Objects in order.

**`$util.log.debug(Object) : Void`**  
Logs the String representation of the provided Object to the requested log stream when request-level and field-level CloudWatch logging is enabled with log level `ALL` or `DEBUG` on an API.

**`$util.log.debug(String, Object...) : Void`**  
Logs the String representation of the provided Objects to the requested log stream when field-level CloudWatch logging is enabled with log level `DEBUG` or log level `ALL` on an API. This utility will replace all variables indicated by "\$1\$1" in the first input format String with the String representation of the provided Objects in order.

**`$util.log.error(Object) : Void`**  
Logs the String representation of the provided Object to the requested log stream when field-level CloudWatch logging is enabled with **any** log level (`ALL`, `INFO`, `DEBUG`, etc.) on an API.

**`$util.log.error(String, Object...) : Void`**  
Logs the String representation of the provided Objects to the requested log stream when field-level CloudWatch logging is enabled with log level `ERROR` or log level `ALL` on an API. This utility will replace all variables indicated by "\$1\$1" in the first input format String with the String representation of the provided Objects in order.

## Return value behavior utils
<a name="utility-helpers-in-return-behavior"></a>

### Return value behavior utils list
<a name="utility-helpers-in-behavior-list"></a>

****`$util.qr()`** and `$util.quiet()` **  
Runs a VTL statement while suppressing the returned value. This is useful for running methods without using temporary placeholders, such as adding items to a map. For example:  

```
#set ($myMap = {})
#set($discard = $myMap.put("id", "first value"))
```
Becomes:  

```
#set ($myMap = {})
$util.qr($myMap.put("id", "first value"))
```  
** `$util.escapeJavaScript(String) : String` **  
Returns the input string as a JavaScript escaped string.  
** `$util.urlEncode(String) : String` **  
Returns the input string as an `application/x-www-form-urlencoded` encoded string.  
** `$util.urlDecode(String) : String` **  
Decodes an `application/x-www-form-urlencoded` encoded string back to its non-encoded form.  
** `$util.base64Encode( byte[] ) : String` **  
Encodes the input into a base64-encoded string.  
** `$util.base64Decode(String) : byte[]` **  
Decodes the data from a base64-encoded string.  
** `$util.parseJson(String) : Object` **  
Takes "stringified" JSON and returns an object representation of the result.  
** `$util.toJson(Object) : String` **  
Takes an object and returns a "stringified" JSON representation of that object.  
** `$util.autoId() : String` **  
Returns a 128-bit randomly generated UUID.  
****`$util.autoUlid() : String`****  
Returns a 128-bit randomly generated ULID (Universally Unique Lexicographically Sortable Identifier).  
****`$util.autoKsuid() : String`****  
Returns a 128-bit randomly generated KSUID (K-Sortable Unique Identifier) base62 encoded as a String with a length of 27.  
** `$util.unauthorized()` **  
Throws `Unauthorized` for the field being resolved. Use this in request or response mapping templates to determine whether to allow the caller to resolve the field.  
** `$util.error(String)` **  
Throws a custom error. Use this in request or response mapping templates to detect an error with the request or with the invocation result.  
** `$util.error(String, String)` **  
Throws a custom error. Use this in request or response mapping templates to detect an error with the request or with the invocation result. You can also specify an `errorType`.  
** `$util.error(String, String, Object)` **  
Throws a custom error. Use this in request or response mapping templates to detect an error with the request or with the invocation result. You can also specify an `errorType` and a `data` field. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response. **Note**: `data` will be filtered based on the query selection set.  
** `$util.error(String, String, Object, Object)` **  
Throws a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` field, a `data` field, and a `errorInfo` field can be specified. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response. **Note**: `data` will be filtered based on the query selection set. The `errorInfo` value will be added to the corresponding `error` block inside `errors` in the GraphQL response. **Note**: `errorInfo` will **NOT** be filtered based on the query selection set.  
** `$util.appendError(String)` **  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Unlike `$util.error(String)`, the template evaluation will not be interrupted, so that data can be returned to the caller.  
** `$util.appendError(String, String)` **  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` can be specified. Unlike `$util.error(String, String)`, the template evaluation will not be interrupted, so that data can be returned to the caller.  
** `$util.appendError(String, String, Object)` **  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` and a `data` field can be specified. Unlike `$util.error(String, String, Object)`, the template evaluation will not be interrupted, so that data can be returned to the caller. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response. **Note**: `data` will be filtered based on the query selection set.  
** `$util.appendError(String, String, Object, Object)` **  
Appends a custom error. This can be used in request or response mapping templates if the template detects an error with the request or with the invocation result. Additionally, an `errorType` field, a `data` field, and a `errorInfo` field can be specified. Unlike `$util.error(String, String, Object, Object)`, the template evaluation will not be interrupted, so that data can be returned to the caller. The `data` value will be added to the corresponding `error` block inside `errors` in the GraphQL response. **Note**: `data` will be filtered based on the query selection set. The `errorInfo` value will be added to the corresponding `error` block inside `errors` in the GraphQL response. **Note**: `errorInfo` will **NOT** be filtered based on the query selection set.  
** `$util.validate(Boolean, String) : void` **  
If the condition is false, throw a CustomTemplateException with the specified message.  
** `$util.validate(Boolean, String, String) : void` **  
If the condition is false, throw a CustomTemplateException with the specified message and error type.  
** `$util.validate(Boolean, String, String, Object) : void` **  
If the condition is false, throw a CustomTemplateException with the specified message and error type, as well as data to return in the response.  
** `$util.isNull(Object) : Boolean` **  
Returns true if the supplied object is null.  
** `$util.isNullOrEmpty(String) : Boolean` **  
Returns true if the supplied data is null or an empty string. Otherwise, returns false.  
** `$util.isNullOrBlank(String) : Boolean` **  
Returns true if the supplied data is null or a blank string. Otherwise, returns false.  
** `$util.defaultIfNull(Object, Object) : Object` **  
Returns the first Object if it is not null. Otherwise, returns second object as a "default Object".  
** `$util.defaultIfNullOrEmpty(String, String) : String` **  
Returns the first String if it is not null or empty. Otherwise, returns second String as a "default String".  
** `$util.defaultIfNullOrBlank(String, String) : String` **  
Returns the first String if it is not null or blank. Otherwise, returns second String as a "default String".  
** `$util.isString(Object) : Boolean` **  
Returns true if Object is a String.  
** `$util.isNumber(Object) : Boolean` **  
Returns true if Object is a Number.  
** `$util.isBoolean(Object) : Boolean` **  
Returns true if Object is a Boolean.  
** `$util.isList(Object) : Boolean` **  
Returns true if Object is a List.  
** `$util.isMap(Object) : Boolean` **  
Returns true if Object is a Map.  
** `$util.typeOf(Object) : String` **  
Returns a String describing the type of the Object. Supported type identifications are: "Null", "Number", "String", "Map", "List", "Boolean". If a type cannot be identified, the return type is "Object".  
** `$util.matches(String, String) : Boolean` **  
Returns true if the specified pattern in the first argument matches the supplied data in the second argument. The pattern must be a regular expression such as `$util.matches("a*b", "aaaaab")`. The functionality is based on [Pattern](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html), which you can reference for further documentation.  
** `$util.authType() : String` **  
Returns a String describing the multi-auth type being used by a request, returning back either "IAM Authorization", "User Pool Authorization", "Open ID Connect Authorization", or "API Key Authorization".  
****`$util.log.info(Object) : Void`****  
Logs the String representation of the provided Object to the requested log stream when request-level and field-level CloudWatch logging is enabled with log level `ALL` on an API.  
****`$util.log.info(String, Object...) : Void`****  
Logs the String representation of the provided Objects to the requested log stream when request-level and field-level CloudWatch logging is enabled with log level `ALL` on an API. This utility will replace all variables indicated by "\$1\$1" in the first input format String with the String representation of the provided Objects in order.  
****`$util.log.error(Object) : Void`****  
Logs the String representation of the provided Object to the requested log stream when field-level CloudWatch logging is enabled with log level `ERROR` or log level `ALL` on an API.  
****`$util.log.error(String, Object...) : Void`****  
Logs the String representation of the provided Objects to the requested log stream when field-level CloudWatch logging is enabled with log level `ERROR` or log level `ALL` on an API. This utility will replace all variables indicated by "\$1\$1" in the first input format String with the String representation of the provided Objects in order.

** `$util.escapeJavaScript(String) : String` **  
Returns the input string as a JavaScript escaped string.

## Resolver authorization
<a name="utility-helpers-in-resolver-auth"></a>

### Resolver authorization list
<a name="utility-helpers-in-resolver-auth-list"></a>

** `$util.unauthorized()` **  
Throws `Unauthorized` for the field being resolved. Use this in request or response mapping templates to determine whether to allow the caller to resolve the field.

# AWS AppSync directives
<a name="aws-appsync-directives"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

AWS AppSync exposes directives to facilitate developer productivity when writing in VTL.

## Directive utils
<a name="utility-helpers-in-directives"></a>

****`#return(Object)`****  
The `#return(Object)` allows you to prematurely return from any mapping template. `#return(Object)` is analogous to the *return* keyword in programming languages, as it will return from the closest scoped block of logic. Using `#return(Object)` inside of a resolver mapping template will return from the resolver. Additionally, using `#return(Object)` from a function mapping template will return from the function and will continue the run to either the next function in the pipeline or the resolver response mapping template.

****`#return`****  
The `#return` directive exhibits the same behaviors as `#return(Object)`, but `null` will be returned instead.

# Time helpers in \$1util.time
<a name="time-helpers-in-util-time"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The `$util.time` variable contains datetime methods to help generate timestamps, convert between datetime formats, and parse datetime strings. The syntax for datetime formats is based on [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) which you can reference for further documentation. We provide some examples below, as well as a list of available methods and descriptions.

## Time utils
<a name="utility-helpers-in-time"></a>

### Time utils list
<a name="utility-helpers-in-time-list"></a>

** `$util.time.nowISO8601() : String` **  
Returns a String representation of UTC in [ISO8601 format](https://en.wikipedia.org/wiki/ISO_8601).

** `$util.time.nowEpochSeconds() : long` **  
Returns the number of seconds from the epoch of 1970-01-01T00:00:00Z to now.

** `$util.time.nowEpochMilliSeconds() : long` **  
Returns the number of milliseconds from the epoch of 1970-01-01T00:00:00Z to now.

** `$util.time.nowFormatted(String) : String` **  
Returns a string of the current timestamp in UTC using the specified format from a String input type.

** `$util.time.nowFormatted(String, String) : String` **  
Returns a string of the current timestamp for a timezone using the specified format and timezone from String input types.

** `$util.time.parseFormattedToEpochMilliSeconds(String, String) : Long` **  
Parses a timestamp passed as a String along with a format containing a time zone, then returns the timestamp as milliseconds since epoch.

** `$util.time.parseFormattedToEpochMilliSeconds(String, String, String) : Long` **  
Parses a timestamp passed as a String along with a format and time zone, then returns the timestamp as milliseconds since epoch.

** `$util.time.parseISO8601ToEpochMilliSeconds(String) : Long` **  
Parses an ISO8601 timestamp passed as a String, then returns the timestamp as milliseconds since epoch.

** `$util.time.epochMilliSecondsToSeconds(long) : long` **  
Converts an epoch milliseconds timestamp to an epoch seconds timestamp.

** `$util.time.epochMilliSecondsToISO8601(long) : String` **  
Converts an epoch milliseconds timestamp to an ISO8601 timestamp.

** `$util.time.epochMilliSecondsToFormatted(long, String) : String` **  
Converts an epoch milliseconds timestamp, passed as long, to a timestamp formatted according to the supplied format in UTC.

** `$util.time.epochMilliSecondsToFormatted(long, String, String) : String` **  
Converts an epoch milliseconds timestamp, passed as a long, to a timestamp formatted according to the supplied format in the supplied timezone.

## Standalone function examples
<a name="standalone-function-examples"></a>

```
$util.time.nowISO8601()                                            : 2018-02-06T19:01:35.749Z
$util.time.nowEpochSeconds()                                       : 1517943695
$util.time.nowEpochMilliSeconds()                                  : 1517943695750
$util.time.nowFormatted("yyyy-MM-dd HH:mm:ssZ")                    : 2018-02-06 19:01:35+0000
$util.time.nowFormatted("yyyy-MM-dd HH:mm:ssZ", "+08:00")          : 2018-02-07 03:01:35+0800
$util.time.nowFormatted("yyyy-MM-dd HH:mm:ssZ", "Australia/Perth") : 2018-02-07 03:01:35+0800
```

## Conversion examples
<a name="conversion-examples"></a>

```
#set( $nowEpochMillis = 1517943695758 )
$util.time.epochMilliSecondsToSeconds($nowEpochMillis)                                     : 1517943695
$util.time.epochMilliSecondsToISO8601($nowEpochMillis)                                     : 2018-02-06T19:01:35.758Z
$util.time.epochMilliSecondsToFormatted($nowEpochMillis, "yyyy-MM-dd HH:mm:ssZ")           : 2018-02-06 19:01:35+0000
$util.time.epochMilliSecondsToFormatted($nowEpochMillis, "yyyy-MM-dd HH:mm:ssZ", "+08:00") : 2018-02-07 03:01:35+0800
```

## Parsing examples
<a name="parsing-examples"></a>

```
$util.time.parseISO8601ToEpochMilliSeconds("2018-02-01T17:21:05.180+08:00")                          : 1517476865180
$util.time.parseFormattedToEpochMilliSeconds("2018-02-02 01:19:22+0800", "yyyy-MM-dd HH:mm:ssZ")     : 1517505562000
$util.time.parseFormattedToEpochMilliSeconds("2018-02-02 01:19:22", "yyyy-MM-dd HH:mm:ss", "+08:00") : 1517505562000
```

## Usage with AWS AppSync defined scalars
<a name="usage-with-aws-scalars"></a>

The following formats are compatible with `AWSDate`, `AWSDateTime`, and `AWSTime`.

```
$util.time.nowFormatted("yyyy-MM-dd[XXX]", "-07:00:30")               : 2018-07-11-07:00
$util.time.nowFormatted("yyyy-MM-dd'T'HH:mm:ss[XXXXX]", "-07:00:30")  : 2018-07-11T15:14:15-07:00:30
```

# List helpers in \$1util.list
<a name="list-helpers-in-util-list"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

`$util.list` contains methods to help with common List operations such as removing or retaining items from a list for filtering use cases.

## List utils
<a name="utility-helpers-in-list-utils"></a>

** `$util.list.copyAndRetainAll(List, List) : List` **  
Makes a shallow copy of the supplied list in the first argument while retaining only the items specified in the second argument, if they are present. All other items will be removed from the copy.

** `$util.list.copyAndRemoveAll(List, List) : List` **  
Makes a shallow copy of the supplied list in the first argument while removing any items where the item is specified in the second argument, if they are present. All other items will be retained in the copy.

** `$util.list.sortList(List, Boolean, String) : List` **  
Sorts a list of objects, which is provided in the first argument. If the second argument is true, the list is sorted in a descending manner; if the second argument is false, the list is sorted in an ascending manner. The third argument is the string name of the property used to sort a list of custom objects. If it's a list of just Strings, Integers, Floats, or Doubles, the third argument can be any random string. If all of the objects are not from the same class, the original list is returned. Only lists containing a maximum of 1000 objects are supported. The following is an example of this utility's usage:   

```
 INPUT:      $util.list.sortList([{"description":"youngest", "age":5},{"description":"middle", "age":45}, {"description":"oldest", "age":85}], false, "description")
 OUTPUT:     [{"description":"middle", "age":45}, {"description":"oldest", "age":85}, {"description":"youngest", "age":5}]
```

# Map helpers in \$1util.map
<a name="utility-helpers-in-map"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

 `$util.map` contains methods to help with common Map operations such as removing or retaining items from a Map for filtering use cases.

## Map utils
<a name="utility-helpers-in-map-list"></a>

** `$util.map.copyAndRetainAllKeys(Map, List) : Map` **  
Makes a shallow copy of the first map while retaining only the keys specified in the list, if they are present. All other keys will be removed from the copy.

** `$util.map.copyAndRemoveAllKeys(Map, List) : Map` **  
Makes a shallow copy of the first map while removing any entries where the key is specified in the list, if they are present. All other keys will be retained in the copy.

# DynamoDB helpers in \$1util.dynamodb
<a name="dynamodb-helpers-in-util-dynamodb"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

`$util.dynamodb` contains helper methods that make it easier to write and read data to Amazon DynamoDB, such as automatic type mapping and formatting. These methods are designed to make mapping primitive types and Lists to the proper DynamoDB input format automatically, which is a `Map` of the format `{ "TYPE" : VALUE }`.

For example, previously, a request mapping template to create a new item in DynamoDB might have looked like this:

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key": {
        "id" : { "S" : "$util.autoId()" }
    },
    "attributeValues" : {
         "title" : { "S" : $util.toJson($ctx.args.title) },
         "author" : { "S" : $util.toJson($ctx.args.author) },
         "version" : { "N", $util.toJson($ctx.args.version) }
    }
}
```

If we wanted to add fields to the object we would have to update the GraphQL query in the schema, as well as the request mapping template. However, we can now restructure our request mapping template so it automatically picks up new fields added in our schema and adds them to DynamoDB with the correct types:

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key": {
        "id" : $util.dynamodb.toDynamoDBJson($util.autoId())
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
```

In the previous example, we are using the `$util.dynamodb.toDynamoDBJson(...)` helper to automatically take the generated id and convert it to the DynamoDB representation of a string attribute. We then take all the arguments and convert them to their DynamoDB representations and output them to the `attributeValues` field in the template.

Each helper has two versions: a version that returns an object (for example, `$util.dynamodb.toString(...)`), and a version that returns the object as a JSON string (for example, `$util.dynamodb.toStringJson(...)`). In the previous example, we used the version that returns the data as a JSON string. If you want to manipulate the object before it's used in the template, you can choose to return an object instead, as shown following:

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key": {
        "id" : $util.dynamodb.toDynamoDBJson($util.autoId())
    },

    #set( $myFoo = $util.dynamodb.toMapValues($ctx.args) )
    #set( $myFoo.version = $util.dynamodb.toNumber(1) )
    #set( $myFoo.timestamp = $util.dynamodb.toString($util.time.nowISO8601()))

    "attributeValues" : $util.toJson($myFoo)
}
```

In the previous example, we are returning the converted arguments as a map instead of a JSON string, and are then adding the `version` and `timestamp` fields before finally outputting them to the `attributeValues` field in the template using `$util.toJson(...)`.

The JSON version of each of the helpers is equivalent to wrapping the non-JSON version in `$util.toJson(...)`. For example, the following statements are exactly the same:

```
$util.toStringJson("Hello, World!")
$util.toJson($util.toString("Hello, World!"))
```

## toDynamoDB
<a name="utility-helpers-in-toDynamoDB"></a>

### toDynamoDB utils list
<a name="utility-helpers-in-toDynamoDB-list"></a>

** `$util.dynamodb.toDynamoDB(Object) : Map` **  
General object conversion tool for DynamoDB that converts input objects to the appropriate DynamoDB representation. It's opinionated about how it represents some types: e.g., it will use lists ("L") rather than sets ("SS", "NS", "BS"). This returns an object that describes the DynamoDB attribute value.  
**String example**  

```
Input:      $util.dynamodb.toDynamoDB("foo")
Output:     { "S" : "foo" }
```
**Number example**  

```
Input:      $util.dynamodb.toDynamoDB(12345)
Output:     { "N" : 12345 }
```
**Boolean example**  

```
Input:      $util.dynamodb.toDynamoDB(true)
Output:     { "BOOL" : true }
```
**List example**  

```
Input:      $util.dynamodb.toDynamoDB([ "foo", 123, { "bar" : "baz" } ])
Output:     {
               "L" : [
                   { "S" : "foo" },
                   { "N" : 123 },
                   {
                       "M" : {
                           "bar" : { "S" : "baz" }
                       }
                   }
               ]
           }
```
**Map example**  

```
Input:      $util.dynamodb.toDynamoDB({ "foo": "bar", "baz" : 1234, "beep": [ "boop"] })
Output:     {
               "M" : {
                   "foo"  : { "S" : "bar" },
                   "baz"  : { "N" : 1234 },
                   "beep" : {
                       "L" : [
                           { "S" : "boop" }
                       ]
                   }
               }
           }
```

****`$util.dynamodb.toDynamoDBJson(Object) : String`** **  
The same as `$util.dynamodb.toDynamoDB(Object) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

## toString utils
<a name="utility-helpers-in-toString"></a>

### toString utils list
<a name="utility-helpers-in-toString-list"></a>

****`$util.dynamodb.toString(String) : String`** **  
Converts an input string to the DynamoDB string format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toString("foo")
Output:     { "S" : "foo" }
```

** `$util.dynamodb.toStringJson(String) : Map` **  
The same as `$util.dynamodb.toString(String) : String`, but returns the DynamoDB attribute value as a JSON encoded string.

** `$util.dynamodb.toStringSet(List<String>) : Map` **  
Converts a list with Strings to the DynamoDB string set format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toStringSet([ "foo", "bar", "baz" ])
Output:     { "SS" : [ "foo", "bar", "baz" ] }
```

** `$util.dynamodb.toStringSetJson(List<String>) : String` **  
The same as `$util.dynamodb.toStringSet(List<String>) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

## toNumber utils
<a name="utility-helpers-in-toNumber"></a>

### toNumber utils list
<a name="utility-helpers-in-toNumber-list"></a>

** `$util.dynamodb.toNumber(Number) : Map` **  
Converts a number to the DynamoDB number format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toNumber(12345)
Output:     { "N" : 12345 }
```

** `$util.dynamodb.toNumberJson(Number) : String` **  
The same as `$util.dynamodb.toNumber(Number) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

** `$util.dynamodb.toNumberSet(List<Number>) : Map` **  
Converts a list of numbers to the DynamoDB number set format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toNumberSet([ 1, 23, 4.56 ])
Output:     { "NS" : [ 1, 23, 4.56 ] }
```

** `$util.dynamodb.toNumberSetJson(List<Number>) : String` **  
The same as `$util.dynamodb.toNumberSet(List<Number>) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

## toBinary utils
<a name="utility-helpers-in-toBinary"></a>

### toBinary utils list
<a name="utility-helpers-in-toBinary-list"></a>

** `$util.dynamodb.toBinary(String) : Map` **  
Converts binary data encoded as a base64 string to DynamoDB binary format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toBinary("foo")
Output:     { "B" : "foo" }
```

** `$util.dynamodb.toBinaryJson(String) : String` **  
The same as `$util.dynamodb.toBinary(String) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

** `$util.dynamodb.toBinarySet(List<String>) : Map` **  
Converts a list of binary data encoded as base64 strings to DynamoDB binary set format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toBinarySet([ "foo", "bar", "baz" ])
Output:     { "BS" : [ "foo", "bar", "baz" ] }
```

** `$util.dynamodb.toBinarySetJson(List<String>) : String` **  
The same as `$util.dynamodb.toBinarySet(List<String>) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

## toBoolean utils
<a name="utility-helpers-in-toBoolean"></a>

### toBoolean utils list
<a name="utility-helpers-in-toBoolean-list"></a>

** `$util.dynamodb.toBoolean(Boolean) : Map` **  
Converts a Boolean to the appropriate DynamoDB Boolean format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toBoolean(true)
Output:     { "BOOL" : true }
```

** `$util.dynamodb.toBooleanJson(Boolean) : String` **  
The same as `$util.dynamodb.toBoolean(Boolean) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

## toNull utils
<a name="utility-helpers-in-toNull"></a>

### toNull utils list
<a name="utility-helpers-in-toNull-list"></a>

** `$util.dynamodb.toNull() : Map` **  
Returns a null in DynamoDB null format. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toNull()
Output:     { "NULL" : null }
```

** `$util.dynamodb.toNullJson() : String` **  
The same as `$util.dynamodb.toNull() : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

## toList utils
<a name="utility-helpers-in-toList"></a>

### toList utils list
<a name="utility-helpers-in-toList-list"></a>

****`$util.dynamodb.toList(List) : Map`** **  
Converts a list of objects to the DynamoDB list format. Each item in the list is also converted to its appropriate DynamoDB format. It's opinionated about how it represents some of the nested objects: e.g., it will use lists ("L") rather than sets ("SS", "NS", "BS"). This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toList([ "foo", 123, { "bar" : "baz" } ])
Output:     {
               "L" : [
                   { "S" : "foo" },
                   { "N" : 123 },
                   {
                       "M" : {
                           "bar" : { "S" : "baz" }
                       }
                   }
               ]
           }
```

** `$util.dynamodb.toListJson(List) : String` **  
The same as `$util.dynamodb.toList(List) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

## toMap utils
<a name="utility-helpers-in-toMap"></a>

### toMap utils list
<a name="utility-helpers-in-toMap-list"></a>

** `$util.dynamodb.toMap(Map) : Map` **  
Converts a map to the DynamoDB map format. Each value in the map is also converted to its appropriate DynamoDB format. It's opinionated about how it represents some of the nested objects: e.g., it will use lists ("L") rather than sets ("SS", "NS", "BS"). This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toMap({ "foo": "bar", "baz" : 1234, "beep": [ "boop"] })
Output:     {
               "M" : {
                   "foo"  : { "S" : "bar" },
                   "baz"  : { "N" : 1234 },
                   "beep" : {
                       "L" : [
                           { "S" : "boop" }
                       ]
                   }
               }
           }
```

** `$util.dynamodb.toMapJson(Map) : String` **  
The same as `$util.dynamodb.toMap(Map) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

** `$util.dynamodb.toMapValues(Map) : Map` **  
Creates a copy of the map where each value has been converted to its appropriate DynamoDB format. It's opinionated about how it represents some of the nested objects: e.g., it will use lists ("L") rather than sets ("SS", "NS", "BS").  

```
Input:      $util.dynamodb.toMapValues({ "foo": "bar", "baz" : 1234, "beep": [ "boop"] })
Output:     {
               "foo"  : { "S" : "bar" },
               "baz"  : { "N" : 1234 },
               "beep" : {
                   "L" : [
                       { "S" : "boop" }
                   ]
               }
           }
```
This is slightly different to `$util.dynamodb.toMap(Map) : Map` as it returns only the contents of the DynamoDB attribute value, but not the whole attribute value itself. For example, the following statements are exactly the same:  

```
$util.dynamodb.toMapValues($map)
$util.dynamodb.toMap($map).get("M")
```

** `$util.dynamodb.toMapValuesJson(Map) : String` **  
The same as `$util.dynamodb.toMapValues(Map) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

## S3Object utils
<a name="utility-helpers-in-S3Object"></a>

### S3Object utils list
<a name="utility-helpers-in-S3Object-list"></a>

** `$util.dynamodb.toS3Object(String key, String bucket, String region) : Map` **  
Converts the key, bucket and region into the DynamoDB S3 Object representation. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toS3Object("foo", "bar", region = "baz")
Output:     { "S" : "{ \"s3\" : { \"key\" : \"foo", \"bucket\" : \"bar", \"region\" : \"baz" } }" }
```

** `$util.dynamodb.toS3ObjectJson(String key, String bucket, String region) : String` **  
The same as `$util.dynamodb.toS3Object(String key, String bucket, String region) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

** `$util.dynamodb.toS3Object(String key, String bucket, String region, String version) : Map` **  
Converts the key, bucket, region and optional version into the DynamoDB S3 Object representation. This returns an object that describes the DynamoDB attribute value.  

```
Input:      $util.dynamodb.toS3Object("foo", "bar", "baz", "beep")
Output:     { "S" : "{ \"s3\" : { \"key\" : \"foo\", \"bucket\" : \"bar\", \"region\" : \"baz\", \"version\" = \"beep\" } }" }
```

** `$util.dynamodb.toS3ObjectJson(String key, String bucket, String region, String version) : String` **  
The same as `$util.dynamodb.toS3Object(String key, String bucket, String region, String version) : Map`, but returns the DynamoDB attribute value as a JSON encoded string.

** `$util.dynamodb.fromS3ObjectJson(String) : Map` **  
Accepts the string value of a DynamoDB S3 Object and returns a map that contains the key, bucket, region and optional version.  

```
Input:      $util.dynamodb.fromS3ObjectJson({ "S" : "{ \"s3\" : { \"key\" : \"foo\", \"bucket\" : \"bar\", \"region\" : \"baz\", \"version\" = \"beep\" } }" })
Output:     { "key" : "foo", "bucket" : "bar", "region" : "baz", "version" : "beep" }
```

# Amazon RDS helpers in \$1util.rds
<a name="rds-helpers-in-util-rds"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

`$util.rds` contains helper methods that format Amazon RDS operations by getting rid of extraneous data in result outputs.

## \$1util.rds utils list
<a name="rds-helpers-in-util-rds-list"></a>

****`$util.rds.toJsonString(String serializedSQLResult): String`****  
Returns a `String` by transforming the stringified raw Amazon Relational Database Service (Amazon RDS) Data API operation result format to a more concise string. The returned string is a serialized list of SQL records of the result set. Every record is represented as a collection of key-value pairs. The keys are the corresponding column names.  
If the corresponding statement in the input was a SQL query that causes a mutation (for example INSERT, UPDATE, DELETE), then an empty list is returned. For example, the query `select * from Books limit 2` provides the raw result from the Amazon RDS Data operation:  

```
{
    "sqlStatementResults": [
        {
            "numberOfRecordsUpdated": 0,
            "records": [
                [
                    {
                        "stringValue": "Mark Twain"
                    },
                    {
                        "stringValue": "Adventures of Huckleberry Finn"
                    },
                    {
                        "stringValue": "978-1948132817"
                    }
                ],
                [
                    {
                        "stringValue": "Jack London"
                    },
                    {
                        "stringValue": "The Call of the Wild"
                    },
                    {
                        "stringValue": "978-1948132275"
                    }
                  ]
            ],
            "columnMetadata": [
                {
                    "isSigned": false,
                    "isCurrency": false,
                    "label": "author",
                    "precision": 200,
                    "typeName": "VARCHAR",
                    "scale": 0,
                    "isAutoIncrement": false,
                    "isCaseSensitive": false,
                    "schemaName": "",
                    "tableName": "Books",
                    "type": 12,
                    "nullable": 0,
                    "arrayBaseColumnType": 0,
                    "name": "author"
                },
                {
                    "isSigned": false,
                    "isCurrency": false,
                    "label": "title",
                    "precision": 200,
                    "typeName": "VARCHAR",
                    "scale": 0,
                    "isAutoIncrement": false,
                    "isCaseSensitive": false,
                    "schemaName": "",
                    "tableName": "Books",
                    "type": 12,
                    "nullable": 0,
                    "arrayBaseColumnType": 0,
                    "name": "title"
                },
                {
                    "isSigned": false,
                    "isCurrency": false,
                    "label": "ISBN-13",
                    "precision": 15,
                    "typeName": "VARCHAR",
                    "scale": 0,
                    "isAutoIncrement": false,
                    "isCaseSensitive": false,
                    "schemaName": "",
                    "tableName": "Books",
                    "type": 12,
                    "nullable": 0,
                    "arrayBaseColumnType": 0,
                    "name": "ISBN-13"
                }
            ]
        }
    ]
}
```
The `util.rds.toJsonString` is:  

```
[
  {
    "author": "Mark Twain",
    "title": "Adventures of Huckleberry Finn",
    "ISBN-13": "978-1948132817"
  },
  {
    "author": "Jack London",
    "title": "The Call of the Wild",
    "ISBN-13": "978-1948132275"
  },
]
```

****`$util.rds.toJsonObject(String serializedSQLResult): Object`****  
This is the same as `util.rds.toJsonString`, but with the result being a JSON `Object`.

# HTTP helpers in \$1util.http
<a name="http-helpers-in-utils-http"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The `$util.http` utility provides helper methods that you can use to manage HTTP request parameters and to add response headers.

## \$1util.http utils list
<a name="http-helpers-in-utils-http-list"></a>

** `$util.http.copyHeaders(Map) : Map` **  
Copies the headers from the map, excluding the following restricted HTTP headers:  
+ transfer-encoding
+ connection
+ host
+ expect
+ keep-alive
+ upgrade
+ proxy-authenticate
+ proxy-authorization
+ te
+ content-length
You can use this utility to forward request headers to your downstream HTTP endpoint.  

```
{
    ...
    "params": {
        ...
        "headers": $util.http.copyHeaders($ctx.request.headers),
        ...
    },
    ...
}
```

**\$1util.http.addResponseHeader(String, Object)**  
Adds a single custom header with the name (`String`) and value (`Object`) of the response. The following limitations apply:  
+ In addition to the list of restricted headers for `copyHeaders(Map)`, header names cannot match any of the following:
  + Access-Control-Allow-Credentials
  + Access-Control-Allow-Origin
  + Access-Control-Expose-Headers
  + Access-Control-Max-Age
  + Access-Control-Allow-Methods
  + Access-Control-Allow-Headers
  + Vary
  + Content-Type
+ Header names can't start with the restricted prefixes `x-amzn-` or `x-amz-`.
+ The size of custom response headers can't exceed 4 KB. This includes header names and values.
+ You should define each response header once per GraphQL operation. However, if you define a custom header with the same name multiple times, the most recent definition appears in the response. All headers count towards the header size limit regardless of naming.
+ Headers with an empty or restricted name `(String)` or a null value `(Object)` will be ignored and yield a `ResponseHeaderError` error that is added to the operation's `errors` output.

```
export function request(ctx) {
  util.http.addResponseHeader('itemsCount', 7)
  util.http.addResponseHeader('render', ctx.args.render)
  return {}
}
```

****`$util.http.addResponseHeaders(Map)`****  
Adds multiple response headers to the response from the specified map of names `(String)` and values `(Object)`. The same limitations listed for the `addResponseHeader(String, Object)` method also apply to this method.  

```
export function request(ctx) {
  const headers = {
    headerInt: 12,
    headerString: 'stringValue',
    headerObject: {
      field1: 7,
      field2: 'string'
    }
  }
  util.http.addResponseHeaders(headers)
  return {}
}
```

# XML helpers in \$1util.xml
<a name="xml-helpers-in-utils-xml"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

`$util.xml` contains helper methods that can make it easier to translate XML responses to JSON or a Dictionary.

## \$1util.xml utils list
<a name="xml-helpers-in-utils-xml-list"></a>

****`$util.xml.toMap(String) : Map`****  
Converts an XML string to a Dictionary.  

```
Input:

<?xml version="1.0" encoding="UTF-8"?>
<posts>
<post>
  <id>1</id>
  <title>Getting started with GraphQL</title>
</post>
</posts>

Output (JSON representation):

{
  "posts":{
    "post":{
      "id":1,
      "title":"Getting started with GraphQL"
    }
  }
}


Input:

<?xml version="1.0" encoding="UTF-8"?>
<posts>
<post>
  <id>1</id>
  <title>Getting started with GraphQL</title>
</post>
<post>
  <id>2</id>
  <title>Getting started with AWS AppSync</title>
</post>
</posts>

Output (JSON representation):

{
  "posts":{
    "post":[
        {
          "id":1,
          "title":"Getting started with GraphQL"
        },
        {
          "id":2,
          "title":"Getting started with AWS AppSync"
        }
    ]
  }
}
```

****`$util.xml.toJsonString(String) : String`****  
Converts an XML string to a JSON string. This is similar to *toMap*, except that the output is a string. This is useful if you want to directly convert and return the XML response from an HTTP object to JSON.

****`$util.xml.toJsonString(String, Boolean) : String`****  
Converts an XML string to a JSON string with an optional Boolean parameter to determine if you want to string-encode the JSON.

# Transformation helpers in \$1util.transform
<a name="transformation-helpers-in-utils-transform"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

`$util.transform` contains helper methods that make it easier to perform complex operations against data sources, such as Amazon DynamoDB filter operations.

## Transformation helpers
<a name="transformation-helpers-conversions"></a>

### Transformation helpers utils list
<a name="transformation-helpers-in-utils-transform-list"></a>

****`$util.transform.toDynamoDBFilterExpression(Map) : Map`****  
Converts an input string to a filter expression for use with DynamoDB.  

```
Input:

$util.transform.toDynamoDBFilterExpression({
    "title":{
      "contains":"Hello World"
    }
  })

Output:

{
    "expression" : "contains(#title, :title_contains)"
    "expressionNames" : {
        "#title" : "title",
    },
    "expressionValues" : {
        ":title_contains" : { "S" : "Hello World" }
    },
}
```

****`$util.transform.toElasticsearchQueryDSL(Map) : Map`****  
Converts the given input into its equivalent OpenSearch Query DSL expression, returning it as a JSON string.  

```
Input:

$util.transform.toElasticsearchQueryDSL({
    "upvotes":{
        "ne":15,
        "range":[
            10,
            20
        ]
    },
    "title":{
        "eq":"hihihi",
        "wildcard":"h*i"
    }
  })

Output:
{
    "bool":{
      "must":[
          {
            "bool":{
              "must":[
                  {
                    "bool":{
                      "must_not":{
                        "term":{
                          "upvotes":15
                        }
                      }
                    }
                  },
                  {
                    "range":{
                      "upvotes":{
                        "gte":10,
                        "lte":20
                      }
                    }
                  }
              ]
            }
          },
          {
            "bool":{
              "must":[
                  {
                    "term":{
                      "title":"hihihi"
                    }
                  },
                  {
                  "wildcard":{
                      "title":"h*i"
                    }
                  }
              ]
            }
          }
      ]
    }
}
```
The default operator is assumed to be AND.

## Transformation helpers subscription filters
<a name="transformation-helpers-conversions-subscription-filters"></a>

### Transformation helpers subscription filters utils list
<a name="transformation-helpers-in-utils-transform-list"></a>

****`$util.transform.toSubscriptionFilter(Map) : Map`****  
Converts a `Map` input object to a `SubscriptionFilter` expression object. The `$util.transform.toSubscriptionFilter` method is used as an input to the `$extensions.setSubscriptionFilter()` extension. For more information, see [Extensions](https://docs.aws.amazon.com/appsync/latest/devguide/extensions).

****`$util.transform.toSubscriptionFilter(Map, List) : Map`****  
Converts a `Map` input object to a `SubscriptionFilter` expression object. The `$util.transform.toSubscriptionFilter` method is used as an input to the `$extensions.setSubscriptionFilter()` extension. For more information, see [Extensions](https://docs.aws.amazon.com/appsync/latest/devguide/extensions).  
The first argument is the `Map` input object that's converted to the `SubscriptionFilter` expression object. The second argument is a `List` of field names that are ignored in the first `Map` input object while constructing the `SubscriptionFilter` expression object.

****`$util.transform.toSubscriptionFilter(Map, List, Map) : Map`****  
Converts a `Map` input object to a `SubscriptionFilter` expression object. The `$util.transform.toSubscriptionFilter` method is used as an input to the `$extensions.setSubscriptionFilter()` extension. For more information, see [Extensions](https://docs.aws.amazon.com/appsync/latest/devguide/extensions).   
The first argument is the `Map` input object that's converted to the `SubscriptionFilter` expression object, the second argument is a `List` of field names that will be ignored in the first `Map` input object, and the third argument is a `Map` input object of strict rules that's included while constructing the `SubscriptionFilter` expression object. These strict rules are included in the `SubscriptionFilter` expression object in such a way that at least one of the rules will be satisfied to pass the subscription filter.

## Subscription filter arguments
<a name="subscription-filter-arguments"></a>

The following table explains the how the arguments of the following utilities are defined:
+ `$util.transform.toSubscriptionFilter(Map) : Map`
+ `$util.transform.toSubscriptionFilter(Map, List) : Map`
+ `$util.transform.toSubscriptionFilter(Map, List, Map) : Map`

------
#### [ Argument 1: Map ]

Argument 1 is a `Map` object with the following key values:
+ field names
+ "and"
+ "or"

For field names as keys, the conditions on these fields' entries are in the form of `"operator" : "value"`. 

The following example shows how entries can be added to the `Map`:

```
"field_name" : {
                    "operator1" : value             
               }

## We can have multiple conditions for the same field_name: 

"field_name" : {
                    "operator1" : value             
                    "operator2" : value
                    .
                    .
                    .                  
               }
```

When a field has two or more conditions on it, all of these conditions are considered to use the OR operation.

The input `Map` can also have "and" and "or" as keys, implying that all entries within these should be joined using AND or OR logic depending on the key. The key values "and" and "or" expect an array of conditions.

```
"and" : [
            
            {
                "field_name1" : {
                    "operator1" : value             
                }
             },
             
             {
                "field_name2" : {
                    "operator1" : value             
                }
             },
             .
             .
        ].
```

Note that you can nest "and" and "or". That is, you can have nested "and"/"or" within another "and"/"or" block. However, this doesn't work for simple fields.

```
"and" : [
            
            {
                "field_name1" : {
                    "operator" : value             
                }
             },
             
             {
                "or" : [
                            {
                                "field_name2" : {
                                    "operator" : value             
                                }
                            },
                            
                            {
                                "field_name3" : {
                                    "operator" : value             
                                }
                            }
              
                        ].
```

The following example shows an input of *argument 1* using `$util.transform.toSubscriptionFilter(Map) : Map`.

**Input(s)**

Argument 1: Map:

```
{
  "percentageUp": {
    "lte": 50,
    "gte": 20
  },
  "and": [
    {
      "title": {
        "ne": "Book1"
      }
    },
    {
      "downvotes": {
        "gt": 2000
      }
    }
  ],
  "or": [
    {
      "author": {
        "eq": "Admin"
      }
    },
    {
      "isPublished": {
        "eq": false
      }
    }
  ]
}
```

**Output**

The result is a `Map` object:

```
{
  "filterGroup": [
    {
      "filters": [
        {
          "fieldName": "percentageUp",
          "operator": "lte",
          "value": 50
        },
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 2000
        },
        {
          "fieldName": "author",
          "operator": "eq",
          "value": "Admin"
        }
      ]
    },
    {
      "filters": [
        {
          "fieldName": "percentageUp",
          "operator": "lte",
          "value": 50
        },
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 2000
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        }
      ]
    },
    {
      "filters": [
        {
          "fieldName": "percentageUp",
          "operator": "gte",
          "value": 20
        },
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 2000
        },
        {
          "fieldName": "author",
          "operator": "eq",
          "value": "Admin"
        }
      ]
    },
    {
      "filters": [
        {
          "fieldName": "percentageUp",
          "operator": "gte",
          "value": 20
        },
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 2000
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        }
      ]
    }
  ]
}
```

------
#### [ Argument 2: List ]

Argument 2 contains a `List` of field names that shouldn't be considered in the input `Map` (argument 1) while constructing the `SubscriptionFilter` expression object. The `List` can also be empty.

The following example shows the inputs of argument 1 and argument 2 using `$util.transform.toSubscriptionFilter(Map, List) : Map`.

**Input(s)**

Argument 1: Map:

```
{

  "percentageUp": {
    "lte": 50,
    "gte": 20
  },
  "and": [
    {
      "title": {
        "ne": "Book1"
      }
    },
    {
      "downvotes": {
        "gt": 20
      }
    }
  ],
  "or": [
    {
      "author": {
        "eq": "Admin"
      }
    },
    {
      "isPublished": {
        "eq": false
      }
    }
  ]
}
```

Argument 2: List:

```
["percentageUp", "author"]
```

**Output**

The result is a `Map` object:

```
{
  "filterGroup": [
    {
      "filters": [
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 20
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        }
      ]
    }
  ]
}
```

------
#### [ Argument 3: Map ]

Argument 3 is a `Map` object that has field names as key values (cannot have "and" or "or"). For field names as keys, the conditions on these fields are entries in the form of `"operator" : "value"`. Unlike argument 1, argument 3 cannot have multiple conditions in the same key. In addition, argument 3 doesn't have an "and" or "or" clause, so there's no nesting involved either.

Argument 3 represents a list of strict rules, which are added to the `SubscriptionFilter` expression object so that **at least one** of these conditions is met to pass the filter.

```
{
  "fieldname1": {
    "operator": value
  },
  "fieldname2": {
    "operator": value
  }
}
.
.
.
```

The following example shows the inputs of *argument 1*, *argument 2*, and *argument 3* using `$util.transform.toSubscriptionFilter(Map, List, Map) : Map`.

**Input(s)**

Argument 1: Map:

```
{
  "percentageUp": {
    "lte": 50,
    "gte": 20
  },
  "and": [
    {
      "title": {
        "ne": "Book1"
      }
    },
    {
      "downvotes": {
        "lt": 20
      }
    }
  ],
  "or": [
    {
      "author": {
        "eq": "Admin"
      }
    },
    {
      "isPublished": {
        "eq": false
      }
    }
  ]
}
```

Argument 2: List:

```
["percentageUp", "author"]
```

Argument 3: Map:

```
{
  "upvotes": {
    "gte": 250
  },
  "author": {
    "eq": "Person1"
  }
}
```

**Output**

The result is a `Map` object:

```
{
  "filterGroup": [
    {
      "filters": [
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 20
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        },
        {
          "fieldName": "upvotes",
          "operator": "gte",
          "value": 250
        }
      ]
    },
    {
      "filters": [
        {
          "fieldName": "title",
          "operator": "ne",
          "value": "Book1"
        },
        {
          "fieldName": "downvotes",
          "operator": "gt",
          "value": 20
        },
        {
          "fieldName": "isPublished",
          "operator": "eq",
          "value": false
        },
        {
          "fieldName": "author",
          "operator": "eq",
          "value": "Person1"
        }
      ]
    }
  ]
}
```

------

# Math helpers in \$1util.math
<a name="math-helpers-in-util-math"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

 `$util.math` contains methods to help with common Math operations. 

## \$1util.math utils list
<a name="math-helpers-in-util-math-list"></a>

** `$util.math.roundNum(Double) : Integer` **  
Takes a double and rounds it to the nearest integer. 

** `$util.math.minVal(Double, Double) : Double` **  
Takes two doubles and returns the minimum value between the two doubles.

** `$util.math.maxVal(Double, Double) : Double` **  
Takes two doubles and returns the maximum value between the two doubles.

** `$util.math.randomDouble() : Double` **  
Returns a random double between 0 and 1.  
This function shouldn't be used for anything that needs high entropy randomness (for example, cryptography).

** `$util.math.randomWithinRange(Integer, Integer) : Integer` **  
Returns a random integer value within the specified range, with the first argument specifying the lower value of the range and the second argument specifying the upper value of the range.   
This function shouldn't be used for anything that needs high entropy randomness (for example, cryptography).

# String helpers in \$1util.str
<a name="str-helpers-in-util-str"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

 `$util.str` contains methods to help with common String operations. 

## \$1util.str utils list
<a name="str-helpers-in-util-str-list"></a>

** `$util.str.toUpper(String) : String` **  
Takes a string and converts it to be entirely uppercase. 

** `$util.str.toLower(String) : String` **  
Takes a string and converts it to be entirely lowercase.

** `$util.str.toReplace(String, String, String) : String` **  
Replaces a substring within a string with another string. The first argument specifies the string on which to perform the replacement operation. The second argument specifies the substring to replace. The third argument specifies the string to replace the second argument with. The following is an example of this utility's usage:   

```
 INPUT:      $util.str.toReplace("hello world", "hello", "mellow")
 OUTPUT:     "mellow world"
```

** `$util.str.normalize(String, String) : String` **  
Normalizes a string using one of the four unicode normalization forms: NFC, NFD, NFKC, or NFKD. The first argument is the string to normalize. The second argument is either "nfc", "nfd", "nfkc", or "nfkd" specifying the normalization type to use for the normalization process.

# Extensions
<a name="extensions"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

`$extensions` contains a set of methods to make additional actions within your resolvers.

## Caching extensions
<a name="caching-extensions-list"></a>

**`$extensions.evictFromApiCache(String, String, Object) : Object`**  
Evicts an item from the AWS AppSync server-side cache. The first argument is the type name. The second argument is the field name. The third argument is an object containing key-value pair items that specify the caching key value. You must put the items in the object in the same order as the caching keys in the cached resolver's `cachingKey`.  
This utility works only for mutations, not queries.

## Subscription extensions
<a name="subscription-extensions-list"></a>

**`$extensions.setSubscriptionFilter(filterJsonObject)`**  
Defines enhanced subscription filters. Each subscription notification event is evaluated against provided subscription filters and delivers notifications to clients if all filters evaluate to `true`. The argument is `filterJsonObject` as described in the following section.  
You can use this extension method only in the response mapping templates of a subscription resolver.

**`$extensions.setSubscriptionInvalidationFilter(filterJsonObject)`**  
Defines subscription invalidation filters. Subscription filters are evaluated against the invalidation payload, then invalidate a given subscription if the filters evaluate to `true`. The argument is `filterJsonObject` as described in the following section.  
You can use this extension method only in the response mapping templates of a subscription resolver.

**`$extensions.invalidateSubscriptions(invalidationJsonObject)`**  
Used to initiate a subscription invalidation from a mutation. The argument is `invalidationJsonObject` as described in the following section.  
This extension can be used only in the response mapping templates of the mutation resolvers.  
You can only use at most five unique `$extensions.invalidateSubscriptions()` method calls in any single request. If you exceed this limit, you will receive a GraphQL error.

## Argument: filterJsonObject
<a name="extensions-setSubscriptionInvalidationFilter"></a>

The JSON object defines either subscription or invalidation filters. It's an array of filters in a `filterGroup`. Each filter is a collection of individual filters.

```
{
    "filterGroup": [
        {
           "filters" : [
                 {
                    "fieldName" : "userId",
                    "operator" : "eq",
                    "value" : 1
                }
           ]
           
        },
        {
           "filters" : [
                {
                    "fieldName" : "group",
                    "operator" : "in",
                    "value" : ["Admin", "Developer"]
                }
           ]
           
        }
    ]
}
```

Each filter has three attributes: 
+ `fieldName` – The GraphQL schema field.
+ `operator` – The operator type.
+ `value` – The values to compare to the subscription notification `fieldName` value.

The following is an example assignment of these attributes:

```
{
 "fieldName" : "severity",
 "operator" : "le",
 "value" : $context.result.severity
}
```

### Field: fieldName
<a name="extensions-fieldName"></a>

The string type `fieldName` refers to a field defined in the GraphQL schema that matches the `fieldName` in the subscription notification payload. When a match is found, the `value` of the GraphQL schema field is compared to the `value` of the subscription notification filter. In the following example, the `fieldName` filter matches the `service` field defined in a given GraphQL type. If the notification payload contains a `service` field with a `value` equivalent to `AWS AppSync`, the filter evaluates to `true`:

```
{
 "fieldName" : "service",
 "operator" : "eq",
 "value" : "AWS AppSync"
}
```

### Field: value
<a name="extensions-value"></a>

The value can be a different type based on the operator:
+ A single number or Boolean
  + String examples: `"test"`, `"service"`
  + Number examples: `1`, `2`, `45.75`
  + Boolean examples: `true`, `false`
+ Pairs of numbers or strings
  + String pair example: `["test1","test2"]`, `["start","end"]`
  + Number pair example: `[1,4]`, `[67,89]`, `[12.45, 95.45]`
+ Arrays of numbers or strings
  + String array example: `["test1","test2","test3","test4","test5"]`
  + Number array example: `[1,2,3,4,5]`, `[12.11,46.13,45.09,12.54,13.89]`

### Field: operator
<a name="extensions-operator"></a>

A case-sensitive string with the following possible values: 


| 
| 
| Operator | Description | Possible value types | 
| --- |--- |--- |
| eq | Equal | integer, float, string, Boolean | 
| ne | Not equal | integer, float, string, Boolean | 
| le | Less than or equal | integer, float, string | 
| lt | Less than | integer, float, string | 
| ge | Greater than or equal | integer, float, string | 
| gt | Greater than | integer, float, string | 
| contains | Checks for a subsequence or value in the set. | integer, float, string | 
| notContains | Checks for the absence of a subsequence or absence of a value in the set. | integer, float, string | 
| beginsWith | Checks for a prefix. | string | 
| in | Checks for matching elements that are in the list. | Array of integer, float, or string | 
| notIn | Checks for matching elements that aren't in the list. | Array of integer, float, or string | 
| between | Between two values | integer, float, string | 
| containsAny | Contains common elements | integer, float, string | 

The following table describes how each operator is used in the subscription notification.

------
#### [ eq (equal) ]

The `eq` operator evaluates to `true` if the subscription notification field value matches and is strictly equal to the filter's value. In the following example, the filter evaluates to `true` if the subscription notification has a `service` field with the value equivalent to `AWS AppSync`.

**Possible value types:** integer, float, string, Boolean

```
{
 "fieldName" : "service",
 "operator" : "eq",
 "value" : "AWS AppSync"
}
```

------
#### [ ne (not equal) ]

The `ne` operator evaluates to `true` if the subscription notification field value is different from the filter's value. In the following example, the filter evaluates to `true` if the subscription notification has a `service` field with a value different from `AWS AppSync`.

**Possible value types:** integer, float, string, Boolean

```
{
 "fieldName" : "service",
 "operator" : "ne",
 "value" : "AWS AppSync"
}
```

------
#### [ le (less or equal) ]

The `le` operator evaluates to `true` if the subscription notification field value is less than or equal to the filter's value. In the following example, the filter evaluates to `true` if the subscription notification has a `size` field with a value less than or equal to `5`.

**Possible value types:** integer, float, string

```
{
 "fieldName" : "size",
 "operator" : "le",
 "value" : 5
}
```

------
#### [ lt (less than) ]

The `lt` operator evaluates to `true` if the subscription notification field value is lower than the filter's value. In the following example, the filter evaluates to `true` if the subscription notification has a `size` field with a value lower than `5`.

**Possible value types:** integer, float, string

```
{
 "fieldName" : "size",
 "operator" : "lt",
 "value" : 5
}
```

------
#### [ ge (greater or equal) ]

The `ge` operator evaluates to `true` if the subscription notification field value is greater than or equal to the filter's value. In the following example, the filter evaluates to `true` if the subscription notification has a `size`field with a value greater than or equal to `5`.

**Possible value types:** integer, float, string

```
{
 "fieldName" : "size",
 "operator" : "ge",
 "value" : 5
}
```

------
#### [ gt (greater than) ]

The `gt` operator evaluates to `true` if the subscription notification field value is greater than the filter's value. In the following example, the filter evaluates to `true` if the subscription notification has a `size` field with a value greater than `5`.

**Possible value types:** integer, float, string

```
{
 "fieldName" : "size",
 "operator" : "gt",
 "value" : 5
}
```

------
#### [ contains ]

The `contains` operator checks for a substring, subsequence, or value in a set or single item. A filter with the `contains` operator evaluates to `true` if the subscription notification field value contains the filter value. In the following example, the filter evaluates to `true` if the subscription notification has a `seats` field with the array value containing the value `10`.

**Possible value types:** integer, float, string

```
{
 "fieldName" : "seats",
 "operator" : "contains",
 "value" : 10
}
```

In another example, the filter evaluates to `true` if the subscription notification has an `event` field with `launch` as substring.

```
{
 "fieldName" : "event",
 "operator" : "contains",
 "value" : "launch"
}
```

------
#### [ notContains ]

The `notContains` operator checks for the absence of a substring, subsequence, or value in a set or single item. The filter with the `notContains` operator evaluates to `true` if the subscription notification field value doesn't contain the filter value. In the following example, the filter evaluates to `true` if the subscription notification has a `seats` field with the array value not containing the value `10`.

**Possible value types:** integer, float, string

```
{
 "fieldName" : "seats",
 "operator" : "notContains",
 "value" : 10
}
```

In another example, filter evaluates to `true` if the subscription notification has an `event` field value without `launch` as its subsequence.

```
{
 "fieldName" : "event",
 "operator" : "notContains",
 "value" : "launch"
}
```

------
#### [ beginsWith ]

The `beginsWith` operator checks for a prefix in a string. The filter containing the `beginsWith` operator evaluates to `true` if the subscription notification field value begins with the filter's value. In the following example, the filter evaluates to `true` if the subscription notification has a `service` field with a value that begins with `AWS`.

**Possible value type:** string

```
{
 "fieldName" : "service",
 "operator" : "beginsWith",
 "value" : "AWS"
}
```

------
#### [ in ]

The `in` operator checks for matching elements in an array. The filter containing the `in` operator evaluates to `true` if the subscription notification field value exists in an array. In the following example, the filter evaluates to `true` if the subscription notification has a `severity` field with one of the values present in the array: `[1,2,3]`.

**Possible value type:** Array of integer, float, or string

```
{
 "fieldName" : "severity",
 "operator" : "in",
 "value" : [1,2,3]
}
```

------
#### [ notIn ]

The `notIn` operator checks for missing elements in an array. The filter containing the `notIn` operator evaluates to `true` if the subscription notification field value doesn't exist in the array. In the following example, the filter evaluates to `true` if the subscription notification has a `severity` field with one of the values not present in the array: `[1,2,3]`.

**Possible value type:** Array of integer, float, or string

```
{
 "fieldName" : "severity",
 "operator" : "notIn",
 "value" : [1,2,3]
}
```

------
#### [ between ]

The `between` operator checks for values between two numbers or strings. The filter containing the `between` operator evaluates to `true` if the subscription notification field value is between the filter's value pair. In the following example, the filter evaluates to `true` if the subscription notification has a `severity` field with values `2`,`3`,`4`.

**Possible value types:** Pair of integer, float, or string

```
{
 "fieldName" : "severity",
 "operator" : "between",
 "value" : [1,5]
}
```

------
#### [ containsAny ]

The `containsAny` operator checks for common elements in arrays. A filter with the `containsAny` operator evaluates to `true` if the intersection of the subscription notification field set value and filter set value is non empty. In the following example, the filter evaluates to `true` if the subscription notification has a `seats` field with an array value containing either `10` or `15`. This means that filter would evaluate to `true` if the subscription notification had a `seats` field value of `[10,11]` or `[15,20,30]`.

**Possible value types:** integer, float, or string

```
{
 "fieldName" : "seats",
 "operator" : "containsAny",
 "value" : [10, 15]
}
```

------

### AND logic
<a name="extensions-AND-logic"></a>

You can combine multiple filters using AND logic by defining multiple entries within the `filters` object in the `filterGroup` array. In the following example, filters evaluate to `true` if the subscription notification has a `userId` field with a value equivalent to `1` AND a `group` field value of either `Admin` or `Developer`.

```
{
    "filterGroup": [
        {
           "filters" : [
                 {
                    "fieldName" : "userId",
                    "operator" : "eq",
                    "value" : 1
                },
                {
                    "fieldName" : "group",
                    "operator" : "in",
                    "value" : ["Admin", "Developer"]
                }
           ]
           
        }
    ]
}
```

### OR logic
<a name="extensions-OR-logic"></a>

You can combine multiple filters using OR logic by defining multiple filter objects within the `filterGroup` array. In the following example, filters evaluate to `true` if the subscription notification has a `userId` field with a value equivalent to `1` OR a `group` field value of either `Admin` or `Developer`.

```
{
    "filterGroup": [
        {
           "filters" : [
                 {
                    "fieldName" : "userId",
                    "operator" : "eq",
                    "value" : 1
                }
           ]
           
        },
        {
           "filters" : [
                {
                    "fieldName" : "group",
                    "operator" : "in",
                    "value" : ["Admin", "Developer"]
                }
           ]
           
        }
    ]
}
```

### Exceptions
<a name="extensions-exceptions"></a>

Note that there are several restrictions for using filters:
+ In the `filters` object, there can be a maximum of five unique `fieldName` items per filter. This means that you can combine a maximum of five individual `fieldName` objects using AND logic.
+ There can be a maximum of twenty values for the `containsAny` operator.
+ There can be a maximum of five values for the `in` and `notIn` operators.
+ Each string can be a maximum of 256 characters.
+ Each string comparison is case sensitive.
+ Nested object filtering allows up to five nested levels of filtering.
+ Each `filterGroup` can have a maximum of 10 `filters`. This means that you can combine a maximum of 10 `filters` using OR logic.
  + The `in` operator is a special case of OR logic. In the following example, there are two `filters`:

    ```
    {
        "filterGroup": [
            {
               "filters" : [
                     {
                        "fieldName" : "userId",
                        "operator" : "eq",
                        "value" : 1
                    },
                    {
                        "fieldName" : "group",
                        "operator" : "in",
                        "value" : ["Admin", "Developer"]
                    }
               ]  
            }
        ]
    }
    ```

    The preceding filter group is evaluated as follows and counts towards the maximum filters limit:

    ```
    {
        "filterGroup": [
            {
               "filters" : [
                     {
                        "fieldName" : "userId",
                        "operator" : "eq",
                        "value" : 1
                    },
                    {
                        "fieldName" : "group",
                        "operator" : "eq",
                        "value" : "Admin"
                    }
               ]  
            },
            {
               "filters" : [
                     {
                        "fieldName" : "userId",
                        "operator" : "eq",
                        "value" : 1
                    },
                    {
                        "fieldName" : "group",
                        "operator" : "eq",
                        "value" : "Developer"
                    }
               ]  
            }
        ]
    }
    ```

## Argument: invalidationJsonObject
<a name="extensions-invalidationJsonObject"></a>

The `invalidationJsonObject` defines the following:
+ `subscriptionField` – The GraphQL schema subscription to invalidate. A single subscription, defined as a string in the `subscriptionField`, is considered for invalidation.
+ `payload` – A key-value pair list that's used as the input for invalidating subscriptions if the invalidation filter evaluates to `true` against their values.

  The following example invalidates subscribed and connected clients using the `onUserDelete` subscription when the invalidation filter defined in the subscription resolver evaluates to `true` against the `payload` value.

  ```
  $extensions.invalidateSubscriptions({
          "subscriptionField": "onUserDelete",
          "payload": {
                  "group": "Developer"
                  "type" : "Full-Time"
        }
      })
  ```

# AWS AppSync resolver mapping template reference for DynamoDB
<a name="resolver-mapping-template-reference-dynamodb"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The AWS AppSync DynamoDB function allows you to use [GraphQL](https://graphql.org) to store and retrieve data in existing Amazon DynamoDB tables in your account by mapping an incoming GraphQL request into a DynamoDB call, and then mapping the DynamoDB response back to GraphQL. This section describes the request and response handlers for supported DynamoDB operations:
+  [GetItem](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-getitem.html) - The GetItem request lets you tell the DynamoDB function to make a GetItem request to DynamoDB, and enables you to specify the key of the item in DynamoDB and whether to use a consistent read or not.
+  [ PutItem ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-putitem.html) - The PutItem request mapping document lets you tell the DynamoDB function to make a PutItem request to DynamoDB, and enables you to specify the key of the item in DynamoDB, the full contents of the item (composed of key and attributeValues), and conditions for the operation to succeed.
+  [ UpdateItem ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-updateitem.html) - The UpdateItem request enables you to tell the DynamoDB function to make a UpdateItem request to DynamoDB and allows you to specify the key of the item in DynamoDB, an update expression describing how to update the item in DynamoDB, and conditions for the operation to succeed.
+  [ DeleteItem ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-deleteitem.html) - The DeleteItem request lets you tell the DynamoDB function to make a DeleteItem request to DynamoDB, and enables you to specify the key of the item in DynamoDB and conditions for the operation to succeed.
+  [ Query ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-query.html) - The Query request object lets you tell the DynamoDB resolver to make a Query request to DynamoDB, and enables you to specify the key expression, which index to use, additional filters, how many items to return, whether to use consistent reads, query direction (forward or backward), and pagination tokens.
+  [ Scan ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-scan.html) - The Scan request lets you tell the DynamoDB function to make a Scan request to DynamoDB, and enables you to specify a filter to exclude results, which index to use, how many items to return, whether to use consistent reads, pagination tokens, and parallel scans.
+  [ Sync ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-sync.html) - The Sync request object lets you retrieve all the results from a DynamoDB table and then receive only the data altered since your last query (the delta updates). Sync requests can only be made to versioned DynamoDB data sources. You can specify a filter to exclude results, how many items to return, pagination Tokens, and when your last Sync operation was started.
+  [ BatchGetItem ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-batch-get-item.html) - The BatchGetItem request object lets you tell the DynamoDB function to make a BatchGetItem request to DynamoDB to retrieve multiple items, potentially across multiple tables. For this request object, you must specify the table names to retrieve the items from and the keys of the items to retrieve from each table.
+  [ BatchDeleteItem ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-batch-delete-item.html) - The BatchDeleteItem request object lets you tell the DynamoDB function to make a BatchWriteItem request to DynamoDB to delete multiple items, potentially across multiple tables. For this request object, you must specify the table names to delete the items from and the keys of the items to delete from each table.
+  [ BatchPutItem ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-batch-put-item.html) - The BatchPutItem request object lets you tell the DynamoDB function to make a BatchWriteItem request to DynamoDB to put multiple items, potentially across multiple tables. For this request object, you must specify the table names to put the items in and the full items to put in each table.
+  [ TransactGetItems ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-transact-get-items.html) - The TransactGetItems request object lets you to tell the DynamoDB function to make a TransactGetItems request to DynamoDB to retrieve multiple items, potentially across multiple tables. For this request object, you must specify the table name of each request item to retrieve the item from and the key of each request item to retrieve from each table.
+  [ TransactWriteItems ](https://docs.aws.amazon.com/appsync/latest/devguide/js-aws-appsync-resolver-reference-dynamodb-transact-write-items.html) - The TransactWriteItems request object lets you tell the DynamoDB function to make a TransactWriteItems request to DynamoDB to write multiple items, potentially to multiple tables. For this request object, you must specify the destination table name of each request item, the operation of each request item to perform, and the key of each request item to write.
+  [ Type system (request mapping) ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.html) - Learn more about how DynamoDB typing is integrated into AWS AppSync requests.
+  [ Type system (response mapping) ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses.html) - Learn more about how DynamoDB types are converted automatically to GraphQL or JSON in a response payload.
+  [Filters](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-filter.html) - Learn more about filters for query and scan operations.
+  [ Condition expressions ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-condition-expressions.html) - Learn more about condition expressions for PutItem, UpdateItem, and DeleteItem operations.
+  [ Transaction condition expressions ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-transaction-condition-expressions.html) - Learn more about condition expressions for TransactWriteItems operations.
+  [ Projections ](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-resolver-mapping-template-reference-dynamodb-projections.html) - Learn more about how to specify attributes in read operations.

# GetItem
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-getitem"></a>

The `GetItem` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `GetItem` request to DynamoDB, and enables you to specify:
+ The key of the item in DynamoDB
+ Whether to use a consistent read or not

The `GetItem` mapping document has the following structure:

```
{
    "version" : "2017-02-28",
    "operation" : "GetItem",
    "key" : {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "consistentRead" : true,
    "projection" : {
        ...
    }
}
```

The fields are defined as follows:

## GetItem fields
<a name="getitem-list"></a>

### GetItem fields list
<a name="getitem-list-col"></a>

 **`version`**   
The template definition version. `2017-02-28` and `2018-05-29` are currently supported. This value is required.

 **`operation`**   
The DynamoDB operation to perform. To perform the `GetItem` DynamoDB operation, this must be set to `GetItem`. This value is required.

 **`key`**   
The key of the item in DynamoDB. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required.

 **`consistentRead`**   
Whether or not to perform a strongly consistent read with DynamoDB. This is optional, and defaults to `false`.

**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-projections). This field is optional.

The item returned from DynamoDB is automatically converted into GraphQL and JSON primitive types, and is available in the mapping context (`$context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses.md).

For more information about response mapping templates, see [Resolver mapping template overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

## Example
<a name="example"></a>

The following example is a mapping template for a GraphQL query `getThing(foo: String!, bar: String!)`:

```
{
    "version" : "2017-02-28",
    "operation" : "GetItem",
    "key" : {
        "foo" : $util.dynamodb.toDynamoDBJson($ctx.args.foo),
        "bar" : $util.dynamodb.toDynamoDBJson($ctx.args.bar)
    },
    "consistentRead" : true
}
```

For more information about the DynamoDB `GetItem` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html).

# PutItem
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-putitem"></a>

The `PutItem` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `PutItem` request to DynamoDB, and enables you to specify the following:
+ The key of the item in DynamoDB
+ The full contents of the item (composed of `key` and `attributeValues`)
+ Conditions for the operation to succeed

The `PutItem` mapping document has the following structure:

```
{
    "version" : "2018-05-29",
    "operation" : "PutItem",
    "customPartitionKey" : "foo",
    "populateIndexFields" : boolean value,
    "key": {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "attributeValues" : {
        "baz" : ... typed value
    },
    "condition" : {
       ...
    },
    "_version" : 1
}
```

The fields are defined as follows:

## PutItem fields
<a name="putitem-list"></a>

### PutItem fields list
<a name="putitem-list-col"></a>

 **`version`**   
The template definition version. `2017-02-28` and `2018-05-29` are currently supported. This value is required.

 **`operation`**   
The DynamoDB operation to perform. To perform the `PutItem` DynamoDB operation, this must be set to `PutItem`. This value is required.

 **`key`**   
The key of the item in DynamoDB. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required.

 **`attributeValues`**   
The rest of the attributes of the item to be put into DynamoDB. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This field is optional.

 **`condition`**   
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `PutItem` request overwrites any existing entry for that item. For more information about conditions, see [Condition expressions](aws-appsync-resolver-mapping-template-reference-dynamodb-condition-expressions.md). This value is optional.

 **`_version`**   
A numeric value that represents the latest known version of an item. This value is optional. This field is used for *Conflict Detection* and is only supported on versioned data sources.

**`customPartitionKey`**  
When enabled, this string value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled (for more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*). When enabled, the processing of the `populateIndexFields` entry is also enabled. This field is optional.

**`populateIndexFields`**  
A boolean value that, when enabled **along with the `customPartitionKey`**, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns. For more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*. This field is optional. 

The item written to DynamoDB is automatically converted into GraphQL and JSON primitive types and is available in the mapping context (`$context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses.md).

For more information about response mapping templates, see [Resolver mapping template overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

## Example 1
<a name="example-1"></a>

The following example is a mapping template for a GraphQL mutation `updateThing(foo: String!, bar: String!, name: String!, version: Int!)`.

If no item with the specified key exists, it’s created. If an item already exists with the specified key, it’s overwritten.

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key": {
        "foo" : $util.dynamodb.toDynamoDBJson($ctx.args.foo),
        "bar" : $util.dynamodb.toDynamoDBJson($ctx.args.bar)
    },
    "attributeValues" : {
        "name"    : $util.dynamodb.toDynamoDBJson($ctx.args.name),
        "version" : $util.dynamodb.toDynamoDBJson($ctx.args.version)
    }
}
```

## Example 2
<a name="example-2"></a>

The following example is a mapping template for a GraphQL mutation `updateThing(foo: String!, bar: String!, name: String!, expectedVersion: Int!)`.

This example checks to be sure the item currently in DynamoDB has the `version` field set to `expectedVersion`.

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key": {
        "foo" : $util.dynamodb.toDynamoDBJson($ctx.args.foo),
        "bar" : $util.dynamodb.toDynamoDBJson($ctx.args.bar)
    },
    "attributeValues" : {
        "name"    : $util.dynamodb.toDynamoDBJson($ctx.args.name),
        #set( $newVersion = $context.arguments.expectedVersion + 1 )
        "version" : $util.dynamodb.toDynamoDBJson($newVersion)
    },
    "condition" : {
        "expression" : "version = :expectedVersion",
        "expressionValues" : {
            ":expectedVersion" : $util.dynamodb.toDynamoDBJson($expectedVersion)
        }
    }
}
```

For more information about the DynamoDB `PutItem` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html).

# UpdateItem
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-updateitem"></a>

The `UpdateItem` request mapping document enables you to tell the AWS AppSync DynamoDB resolver to make a `UpdateItem` request to DynamoDB and allows you to specify the following:
+ The key of the item in DynamoDB
+ An update expression describing how to update the item in DynamoDB
+ Conditions for the operation to succeed

The `UpdateItem` mapping document has the following structure:

```
{
    "version" : "2018-05-29",
    "operation" : "UpdateItem",
    "customPartitionKey" : "foo",
    "populateIndexFields" : boolean value,
    "key": {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "update" : {
        "expression" : "someExpression",
        "expressionNames" : {
           "#foo" : "foo"
       },
       "expressionValues" : {
           ":bar" : ... typed value
       }
    },
    "condition" : {
        ...
    },
    "_version" : 1
}
```

The fields are defined as follows:

## UpdateItem fields
<a name="updateitem-list"></a>

### UpdateItem fields list
<a name="updateitem-list-col"></a>

 **`version`**   
The template definition version. `2017-02-28` and `2018-05-29` are currently supported. This value is required.

 **`operation`**   
The DynamoDB operation to perform. To perform the `UpdateItem` DynamoDB operation, this must be set to `UpdateItem`. This value is required.

 **`key`**   
The key of the item in DynamoDB. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about specifying a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required.

 **`update`**   
The `update` section lets you specify an update expression that describes how to update the item in DynamoDB. For more information about how to write update expressions, see the [DynamoDB UpdateExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html). This section is required.  
The `update` section has three components:    
** `expression` **  
The update expression. This value is required.  
** `expressionNames` **  
The substitutions for expression attribute *name* placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the `expression`, and the value must be a string corresponding to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the `expression`.  
** `expressionValues` **  
The substitutions for expression attribute *value* placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the `expression`, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This must be specified. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the `expression`.

 **`condition`**   
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `UpdateItem` request updates the existing entry regardless of its current state. For more information about conditions, see [Condition expressions](aws-appsync-resolver-mapping-template-reference-dynamodb-condition-expressions.md). This value is optional.

 **`_version`**   
A numeric value that represents the latest known version of an item. This value is optional. This field is used for *Conflict Detection* and is only supported on versioned data sources.

**`customPartitionKey`**  
When enabled, this string value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled (for more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*). When enabled, the processing of the `populateIndexFields` entry is also enabled. This field is optional.

**`populateIndexFields`**  
A boolean value that, when enabled **along with the `customPartitionKey`**, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns. For more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*. This field is optional.

The item updated in DynamoDB is automatically converted into GraphQL and JSON primitive types and is available in the mapping context (`$context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses.md).

For more information about response mapping templates, see [Resolver mapping template overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

## Example 1
<a name="id3"></a>

The following example is a mapping template for the GraphQL mutation `upvote(id: ID!)`.

In this example, an item in DynamoDB has its `upvotes` and `version` fields incremented by 1.

```
{
    "version" : "2017-02-28",
    "operation" : "UpdateItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },
    "update" : {
        "expression" : "ADD #votefield :plusOne, version :plusOne",
        "expressionNames" : {
            "#votefield" : "upvotes"
        },
        "expressionValues" : {
            ":plusOne" : { "N" : 1 }
        }
    }
}
```

## Example 2
<a name="id4"></a>

The following example is a mapping template for a GraphQL mutation `updateItem(id: ID!, title: String, author: String, expectedVersion: Int!)`.

This is a complex example that inspects the arguments and dynamically generates the update expression that only includes the arguments that have been provided by the client. For example, if `title` and `author` are omitted, they are not updated. If an argument is specified but its value is `null`, then that field is deleted from the object in DynamoDB. Finally, the operation has a condition, which verifies whether the item currently in DynamoDB has the `version` field set to `expectedVersion`:

```
{
    "version" : "2017-02-28",

    "operation" : "UpdateItem",

    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },

    ## Set up some space to keep track of things we're updating **
    #set( $expNames  = {} )
    #set( $expValues = {} )
    #set( $expSet = {} )
    #set( $expAdd = {} )
    #set( $expRemove = [] )

    ## Increment "version" by 1 **
    $!{expAdd.put("version", ":newVersion")}
    $!{expValues.put(":newVersion", { "N" : 1 })}

    ## Iterate through each argument, skipping "id" and "expectedVersion" **
    #foreach( $entry in $context.arguments.entrySet() )
        #if( $entry.key != "id" && $entry.key != "expectedVersion" )
            #if( (!$entry.value) && ("$!{entry.value}" == "") )
                ## If the argument is set to "null", then remove that attribute from the item in DynamoDB **

                #set( $discard = ${expRemove.add("#${entry.key}")} )
                $!{expNames.put("#${entry.key}", "$entry.key")}
            #else
                ## Otherwise set (or update) the attribute on the item in DynamoDB **

                $!{expSet.put("#${entry.key}", ":${entry.key}")}
                $!{expNames.put("#${entry.key}", "$entry.key")}

                #if( $entry.key == "ups" || $entry.key == "downs" )
                    $!{expValues.put(":${entry.key}", { "N" : $entry.value })}
                #else
                    $!{expValues.put(":${entry.key}", { "S" : "${entry.value}" })}
                #end
            #end
        #end
    #end

    ## Start building the update expression, starting with attributes we're going to SET **
    #set( $expression = "" )
    #if( !${expSet.isEmpty()} )
        #set( $expression = "SET" )
        #foreach( $entry in $expSet.entrySet() )
            #set( $expression = "${expression} ${entry.key} = ${entry.value}" )
            #if ( $foreach.hasNext )
                #set( $expression = "${expression}," )
            #end
        #end
    #end

    ## Continue building the update expression, adding attributes we're going to ADD **
    #if( !${expAdd.isEmpty()} )
        #set( $expression = "${expression} ADD" )
        #foreach( $entry in $expAdd.entrySet() )
            #set( $expression = "${expression} ${entry.key} ${entry.value}" )
            #if ( $foreach.hasNext )
                #set( $expression = "${expression}," )
            #end
        #end
    #end

    ## Continue building the update expression, adding attributes we're going to REMOVE **
    #if( !${expRemove.isEmpty()} )
        #set( $expression = "${expression} REMOVE" )

        #foreach( $entry in $expRemove )
            #set( $expression = "${expression} ${entry}" )
            #if ( $foreach.hasNext )
                #set( $expression = "${expression}," )
            #end
        #end
    #end

    ## Finally, write the update expression into the document, along with any expressionNames and expressionValues **
    "update" : {
        "expression" : "${expression}"
        #if( !${expNames.isEmpty()} )
            ,"expressionNames" : $utils.toJson($expNames)
        #end
        #if( !${expValues.isEmpty()} )
            ,"expressionValues" : $utils.toJson($expValues)
        #end
    },

    "condition" : {
        "expression"       : "version = :expectedVersion",
        "expressionValues" : {
            ":expectedVersion" : $util.dynamodb.toDynamoDBJson($ctx.args.expectedVersion)
        }
    }
}
```

For more information about the DynamoDB `UpdateItem` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html).

# DeleteItem
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-deleteitem"></a>

The `DeleteItem` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `DeleteItem` request to DynamoDB, and enables you to specify the following:
+ The key of the item in DynamoDB
+ Conditions for the operation to succeed

The `DeleteItem` mapping document has the following structure:

```
{
    "version" : "2018-05-29",
    "operation" : "DeleteItem",
    "customPartitionKey" : "foo",
    "populateIndexFields" : boolean value,
    "key": {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "condition" : {
        ...
    },
    "_version" : 1
}
```

The fields are defined as follows:

## DeleteItem fields
<a name="deleteitem-list"></a>

### DeleteItem fields list
<a name="deleteitem-list-col"></a>

** `version` **  
The template definition version. `2017-02-28` and `2018-05-29` are currently supported. This value is required.

** `operation` **  
The DynamoDB operation to perform. To perform the `DeleteItem` DynamoDB operation, this must be set to `DeleteItem`. This value is required.

** `key` **  
The key of the item in DynamoDB. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about specifying a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required.

** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `DeleteItem` request deletes an item regardless of its current state. For more information about conditions, see [Condition expressions](aws-appsync-resolver-mapping-template-reference-dynamodb-condition-expressions.md). This value is optional.

** `_version` **  
A numeric value that represents the latest known version of an item. This value is optional. This field is used for *Conflict Detection* and is only supported on versioned data sources.

**`customPartitionKey`**  
When enabled, this string value modifies the format of the `ds_sk` and `ds_pk` records used by the delta sync table when versioning has been enabled (for more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*). When enabled, the processing of the `populateIndexFields` entry is also enabled. This field is optional.

**`populateIndexFields`**  
A boolean value that, when enabled **along with the `customPartitionKey`**, creates new entries for each record in the delta sync table, specifically in the `gsi_ds_pk` and `gsi_ds_sk` columns. For more information, see [Conflict detection and sync](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html) in the *AWS AppSync Developer Guide*. This field is optional. 

The item deleted from DynamoDB is automatically converted into GraphQL and JSON primitive types and is available in the mapping context (`$context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses.md).

For more information about response mapping templates, see [Resolver mapping template overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

## Example 1
<a name="id6"></a>

The following example is a mapping template for a GraphQL mutation `deleteItem(id: ID!)`. If an item exists with this ID, it’s deleted.

```
{
    "version" : "2017-02-28",
    "operation" : "DeleteItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    }
}
```

## Example 2
<a name="id7"></a>

The following example is a mapping template for a GraphQL mutation `deleteItem(id: ID!, expectedVersion: Int!)`. If an item exists with this ID, it’s deleted, but only if its `version` field set to `expectedVersion`:

```
{
    "version" : "2017-02-28",
    "operation" : "DeleteItem",
    "key" : {
        "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id)
    },
    "condition" : {
        "expression"       : "attribute_not_exists(id) OR version = :expectedVersion",
        "expressionValues" : {
            ":expectedVersion" : $util.dynamodb.toDynamoDBJson($expectedVersion)
        }
    }
}
```

For more information about the DynamoDB `DeleteItem` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html).

# Query
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-query"></a>

The `Query` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `Query` request to DynamoDB, and enables you to specify the following:
+ Key expression
+ Which index to use
+ Any additional filter
+ How many items to return
+ Whether to use consistent reads
+ query direction (forward or backward)
+ Pagination token

The `Query` mapping document has the following structure:

```
{
    "version" : "2017-02-28",
    "operation" : "Query",
    "query" : {
        "expression" : "some expression",
        "expressionNames" : {
            "#foo" : "foo"
        },
        "expressionValues" : {
            ":bar" : ... typed value
        }
    },
    "index" : "fooIndex",
    "nextToken" : "a pagination token",
    "limit" : 10,
    "scanIndexForward" : true,
    "consistentRead" : false,
    "select" : "ALL_ATTRIBUTES" | "ALL_PROJECTED_ATTRIBUTES" | "SPECIFIC_ATTRIBUTES",
    "filter" : {
        ...
    },
    "projection" : {
        ...
    }
}
```

The fields are defined as follows:

## Query fields
<a name="query-list"></a>

### Query fields list
<a name="query-list-col"></a>

** `version` **  
The template definition version. `2017-02-28` and `2018-05-29` are currently supported. This value is required.

** `operation` **  
The DynamoDB operation to perform. To perform the `Query` DynamoDB operation, this must be set to `Query`. This value is required.

** `query` **  
The `query` section lets you specify a key condition expression that describes which items to retrieve from DynamoDB. For more information about how to write key condition expressions, see the [DynamoDB KeyConditions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.KeyConditions.html) . This section must be specified.    
** `expression` **  
The query expression. This field must be specified.  
** `expressionNames` **  
The substitutions for expression attribute *name* placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the `expression`, and the value must be a string corresponding to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the `expression`.  
** `expressionValues` **  
The substitutions for expression attribute *value* placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the `expression`, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the `expression`.

** `filter` **  
An additional filter that can be used to filter the results from DynamoDB before they are returned. For more information about filters, see [Filters](aws-appsync-resolver-mapping-template-reference-dynamodb-filter.md). This field is optional.

** `index` **  
The name of the index to query. The DynamoDB query operation allows you to scan on Local Secondary Indexes and Global Secondary Indexes in addition to the primary key index for a hash key. If specified, this tells DynamoDB to query the specified index. If omitted, the primary key index is queried.

** `nextToken` **  
The pagination token to continue a previous query. This would have been obtained from a previous query. This field is optional.

** `limit` **  
The maximum number of items to evaluate (not necessarily the number of matching items). This field is optional.

** `scanIndexForward` **  
A boolean indicating whether to query forwards or backwards. This field is optional, and defaults to `true`.

** `consistentRead` **  
A boolean indicating whether to use consistent reads when querying DynamoDB. This field is optional, and defaults to `false`.

** `select` **  
By default, the AWS AppSync DynamoDB resolver only returns attributes that are projected into the index. If more attributes are required, you can set this field. This field is optional. The supported values are:    
** `ALL_ATTRIBUTES` **  
Returns all of the item attributes from the specified table or index. If you query a local secondary index, DynamoDB fetches the entire item from the parent table for each matching item in the index. If the index is configured to project all item attributes, all of the data can be obtained from the local secondary index and no fetching is required.  
** `ALL_PROJECTED_ATTRIBUTES` **  
Allowed only when querying an index. Retrieves all attributes that have been projected into the index. If the index is configured to project all attributes, this return value is equivalent to specifying `ALL_ATTRIBUTES`.  
**`SPECIFIC_ATTRIBUTES`**  
Returns only the attributes listed in the `projection`'s `expression`. This return value is equivalent to specifying the `projection`'s `expression` without specifying any value for `Select`.

**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-projections). This field is optional.

The results from DynamoDB are automatically converted into GraphQL and JSON primitive types and are available in the mapping context (`$context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses.md).

For more information about response mapping templates, see [Resolver mapping template overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

The results have the following structure:

```
{
    items = [ ... ],
    nextToken = "a pagination token",
    scannedCount = 10
}
```

The fields are defined as follows:

** `items` **  
A list containing the items returned by the DynamoDB query.

** `nextToken` **  
If there might be more results, `nextToken` contains a pagination token that you can use in another request. Note that AWS AppSync encrypts and obfuscates the pagination token returned from DynamoDB. This prevents your table data from being inadvertently leaked to the caller. Also note that these pagination tokens cannot be used across different resolvers.

** `scannedCount` **  
The number of items that matched the query condition expression, before a filter expression (if present) was applied.

## Example
<a name="id9"></a>

The following example is a mapping template for a GraphQL query `getPosts(owner: ID!)`.

In this example, a global secondary index on a table is queried to return all posts owned by the specified ID.

```
{
    "version" : "2017-02-28",
    "operation" : "Query",
    "query" : {
        "expression" : "ownerId = :ownerId",
        "expressionValues" : {
            ":ownerId" : $util.dynamodb.toDynamoDBJson($context.arguments.owner)
        }
    },
    "index" : "owner-index"
}
```

For more information about the DynamoDB `Query` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html).

# Scan
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-scan"></a>

The `Scan` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `Scan` request to DynamoDB, and enables you to specify the following:
+ A filter to exclude results
+ Which index to use
+ How many items to return
+ Whether to use consistent reads
+ Pagination token
+ Parallel scans

The `Scan` mapping document has the following structure:

```
{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "index" : "fooIndex",
    "limit" : 10,
    "consistentRead" : false,
    "nextToken" : "aPaginationToken",
    "totalSegments" : 10,
    "segment" : 1,
    "filter" : {
        ...
    },
    "projection" : {
        ...
    }
}
```

The fields are defined as follows:

## Scan fields
<a name="scan-list"></a>

### Scan fields list
<a name="scan-list-col"></a>

** `version` **  
The template definition version. `2017-02-28` and `2018-05-29` are currently supported. This value is required.

** `operation` **  
The DynamoDB operation to perform. To perform the `Scan` DynamoDB operation, this must be set to `Scan`. This value is required.

** `filter` **  
A filter that can be used to filter the results from DynamoDB before they are returned. For more information about filters, see [Filters](aws-appsync-resolver-mapping-template-reference-dynamodb-filter.md). This field is optional.

** `index` **  
The name of the index to query. The DynamoDB query operation allows you to scan on Local Secondary Indexes and Global Secondary Indexes in addition to the primary key index for a hash key. If specified, this tells DynamoDB to query the specified index. If omitted, the primary key index is queried.

** `limit` **  
The maximum number of items to evaluate at a single time. This field is optional.

** `consistentRead` **  
A Boolean that indicates whether to use consistent reads when querying DynamoDB. This field is optional, and defaults to `false`.

** `nextToken` **  
The pagination token to continue a previous query. This would have been obtained from a previous query. This field is optional.

** `select` **  
By default, the AWS AppSync DynamoDB resolver only returns whatever attributes are projected into the index. If more attributes are required, then this field can be set. This field is optional. The supported values are:    
** `ALL_ATTRIBUTES` **  
Returns all of the item attributes from the specified table or index. If you query a local secondary index, DynamoDB fetches the entire item from the parent table for each matching item in the index. If the index is configured to project all item attributes, all of the data can be obtained from the local secondary index and no fetching is required.  
** `ALL_PROJECTED_ATTRIBUTES` **  
Allowed only when querying an index. Retrieves all attributes that have been projected into the index. If the index is configured to project all attributes, this return value is equivalent to specifying `ALL_ATTRIBUTES`.  
**`SPECIFIC_ATTRIBUTES`**  
Returns only the attributes listed in the `projection`'s `expression`. This return value is equivalent to specifying the `projection`'s `expression` without specifying any value for `Select`.

** `totalSegments` **  
The number of segments to partition the table by when performing a parallel scan. This field is optional, but must be specified if `segment` is specified.

** `segment` **  
The table segment in this operation when performing a parallel scan. This field is optional, but must be specified if `totalSegments` is specified.

**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-projections). This field is optional.

The results returned by the DynamoDB scan are automatically converted into GraphQL and JSON primitive types and is available in the mapping context (`$context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses.md).

For more information about response mapping templates, see [Resolver mapping template overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

The results have the following structure:

```
{
    items = [ ... ],
    nextToken = "a pagination token",
    scannedCount = 10
}
```

The fields are defined as follows:

** `items` **  
A list containing the items returned by the DynamoDB scan.

** `nextToken` **  
If there might be more results, `nextToken` contains a pagination token that you can use in another request. AWS AppSync encrypts and obfuscates the pagination token returned from DynamoDB. This prevents your table data from being inadvertently leaked to the caller. Also, these pagination tokens can’t be used across different resolvers.

** `scannedCount` **  
The number of items that were retrieved by DynamoDB before a filter expression (if present) was applied.

## Example 1
<a name="id11"></a>

The following example is a mapping template for the GraphQL query: `allPosts`.

In this example, all entries in the table are returned.

```
{
    "version" : "2017-02-28",
    "operation" : "Scan"
}
```

## Example 2
<a name="id12"></a>

The following example is a mapping template for the GraphQL query: `postsMatching(title: String!)`.

In this example, all entries in the table are returned where the title starts with the `title` argument.

```
{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "filter" : {
        "expression" : "begins_with(title, :title)",
        "expressionValues" : {
            ":title" : $util.dynamodb.toDynamoDBJson($context.arguments.title)
        },
    }
}
```

For more information about the DynamoDB `Scan` API, see the [DynamoDB API documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html).

# Sync
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-sync"></a>

The `Sync` request mapping document lets you retrieve all the results from a DynamoDB table and then receive only the data altered since your last query (the delta updates). `Sync` requests can only be made to versioned DynamoDB data sources. You can specify the following:
+ A filter to exclude results
+ How many items to return
+ Pagination Token
+ When your last `Sync` operation was started

The `Sync` mapping document has the following structure:

```
{
    "version" : "2018-05-29",
    "operation" : "Sync",
    "basePartitionKey": "Base Tables PartitionKey",
    "deltaIndexName": "delta-index-name",
    "limit" : 10,
    "nextToken" : "aPaginationToken",
    "lastSync" :  1550000000000,
    "filter" : {
        ...
    }
}
```

The fields are defined as follows:

## Sync fields
<a name="sync-list"></a>

### Sync fields list
<a name="sync-list-col"></a>

** `version` **  
The template definition version. Only `2018-05-29` is currently supported. This value is required.

** `operation` **  
The DynamoDB operation to perform. To perform the `Sync` operation, this must be set to `Sync`. This value is required.

** `filter` **  
A filter that can be used to filter the results from DynamoDB before they are returned. For more information about filters, see [Filters](aws-appsync-resolver-mapping-template-reference-dynamodb-filter.md). This field is optional.

** `limit` **  
The maximum number of items to evaluate at a single time. This field is optional. If omitted, the default limit will be set to `100` items. The maximum value for this field is `1000` items.

** `nextToken` **  
The pagination token to continue a previous query. This would have been obtained from a previous query. This field is optional.

** `lastSync` **  
The moment, in epoch milliseconds, when the last successful `Sync` operation started. If specified, only items that have changed after `lastSync` are returned. This field is optional, and should only be populated after retrieving all pages from an initial `Sync` operation. If omitted, results from the *Base* table will be returned, otherwise, results from the *Delta* table will be returned.

**`basePartitionKey`**  
The partition key of the *Base* table used when performing a `Sync` operation. This field allows a `Sync` operation to be performed when the table utilizes a custom partition key. This is an optional field.

**`deltaIndexName`**  
The index used for the `Sync` operation. This index is required to enable a `Sync` operation on the whole delta store table when the table uses a custom partition key. The `Sync` operation will be performed on the GSI (created on `gsi_ds_pk` and `gsi_ds_sk`). This field is optional.

The results returned by the DynamoDB sync are automatically converted into GraphQL and JSON primitive types and are available in the mapping context (`$context.result`).

For more information about DynamoDB type conversion, see [Type system (response mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses.md).

For more information about response mapping templates, see [Resolver mapping template overview](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview).

The results have the following structure:

```
{
    items = [ ... ],
    nextToken = "a pagination token",
    scannedCount = 10,
    startedAt = 1550000000000
}
```

The fields are defined as follows:

** `items` **  
A list containing the items returned by the sync.

** `nextToken` **  
If there might be more results, `nextToken` contains a pagination token that you can use in another request. AWS AppSync encrypts and obfuscates the pagination token returned from DynamoDB. This prevents your table data from being inadvertently leaked to the caller. Also, these pagination tokens can’t be used across different resolvers.

** `scannedCount` **  
The number of items that were retrieved by DynamoDB before a filter expression (if present) was applied.

** `startedAt` **  
The moment, in epoch milliseconds, when the sync operation started that you can store locally and use in another request as your `lastSync` argument. If a pagination token was included in the request, this value will be the same as the one returned by the request for the first page of results.

## Example
<a name="id14"></a>

The following example is a mapping template for the GraphQL query: `syncPosts(nextToken: String, lastSync: AWSTimestamp)`.

In this example, if `lastSync` is omitted, all entries in the base table are returned. If `lastSync` is supplied, only the entries in the delta sync table that have changed since `lastSync` are returned.

```
{
    "version" : "2018-05-29",
    "operation" : "Sync",
    "limit": 100,
    "nextToken": $util.toJson($util.defaultIfNull($ctx.args.nextToken, null)),
    "lastSync": $util.toJson($util.defaultIfNull($ctx.args.lastSync, null))
}
```

# BatchGetItem
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-batch-get-item"></a>

The `BatchGetItem` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `BatchGetItem` request to DynamoDB to retrieve multiple items, potentially across multiple tables. For this request template, you must specify the following:
+ The table names where to retrieve the items from
+ The keys of the items to retrieve from each table

The DynamoDB `BatchGetItem` limits apply and **no condition expression** can be provided.

The `BatchGetItem` mapping document has the following structure:

```
{
    "version" : "2018-05-29",
    "operation" : "BatchGetItem",
    "tables" : {
        "table1": {
           "keys": [
              ## Item to retrieve Key
              {
                   "foo" : ... typed value,
                   "bar" : ... typed value
              },
              ## Item2 to retrieve Key
              {
                   "foo" : ... typed value,
                   "bar" : ... typed value
              }
            ],
            "consistentRead": true|false,            
            "projection" : {
                 ...
            }
        },
        "table2": {
           "keys": [
              ## Item3 to retrieve Key
              {
                   "foo" : ... typed value,
                   "bar" : ... typed value
              },
              ## Item4 to retrieve Key
              {
                   "foo" : ... typed value,
                   "bar" : ... typed value
              }
            ],
            "consistentRead": true|false,
            "projection" : {
                 ...
            }
        }
    }
}
```

The fields are defined as follows:

## BatchGetItem fields
<a name="BatchGetItem-list"></a>

### BatchGetItem fields list
<a name="BatchGetItem-list-col"></a>

** `version` **  
The template definition version. Only `2018-05-29` is supported. This value is required.

** `operation` **  
The DynamoDB operation to perform. To perform the `BatchGetItem` DynamoDB operation, this must be set to `BatchGetItem`. This value is required.

** `tables` **  
The DynamoDB tables to retrieve the items from. The value is a map where table names are specified as the keys of the map. At least one table must be provided. This `tables` value is required.    
** `keys` **  
List of DynamoDB keys representing the primary key of the items to retrieve. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md).  
** `consistentRead` **  
Whether to use a consistent read when executing a *GetItem* operation. This value is optional and defaults to *false*.  
**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-projections). This field is optional.

Things to remember:
+ If an item has not been retrieved from the table, a *null* element appears in the data block for that table.
+ Invocation results are sorted per table, based on the order in which they were provided inside the request mapping template.
+ Each `Get` command inside a `BatchGetItem` is atomic, however, a batch can be partially processed. If a batch is partially processed due to an error, the unprocessed keys are returned as part of the invocation result inside the *unprocessedKeys* block.
+  `BatchGetItem` is limited to 100 keys.

For the following example request mapping template:

```
{
  "version": "2018-05-29",
  "operation": "BatchGetItem",
  "tables": {
    "authors": [
        {
          "author_id": {
            "S": "a1"
          }
        },
    ],
    "posts": [
        {
          "author_id": {
            "S": "a1"
          },
          "post_id": {
            "S": "p2"
          }
        }
    ],
  }
}
```

The invocation result available in `$ctx.result` is as follows:

```
{
   "data": {
     "authors": [null],
     "posts": [
        # Was retrieved
        {
          "author_id": "a1",
          "post_id": "p2",
          "post_title": "title",
          "post_description": "description",
        }
     ]
   },
   "unprocessedKeys": {
     "authors": [
        # This item was not processed due to an error
        {
          "author_id": "a1"
        }
      ],
     "posts": []
   }
}
```

The `$ctx.error` contains details about the error. The keys **data**, **unprocessedKeys**, and each table key that was provided in the request mapping template are guaranteed to be present in the invocation result. Items that have been deleted appear in the **data** block. Items that haven’t been processed are marked as *null* inside the data block and are placed inside the **unprocessedKeys** block.

For a more complete example, follow the DynamoDB Batch tutorial with AppSync here [Tutorial: DynamoDB batch resolvers](tutorial-dynamodb-batch.md#aws-appsync-tutorial-dynamodb-batch).

# BatchDeleteItem
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-batch-delete-item"></a>

The `BatchDeleteItem` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `BatchWriteItem` request to DynamoDB to delete multiple items, potentially across multiple tables. For this request template, you must specify the following:
+ The table names where to delete the items from
+ The keys of the items to delete from each table

The DynamoDB `BatchWriteItem` limits apply and **no condition expression** can be provided.

The `BatchDeleteItem` mapping document has the following structure:

```
{
    "version" : "2018-05-29",
    "operation" : "BatchDeleteItem",
    "tables" : {
        "table1": [
        ## Item to delete Key
        {
             "foo" : ... typed value,
             "bar" : ... typed value
        },
        ## Item2 to delete Key
        {
             "foo" : ... typed value,
             "bar" : ... typed value
        }],
        "table2": [
        ## Item3 to delete Key
        {
             "foo" : ... typed value,
             "bar" : ... typed value
        },
        ## Item4 to delete Key
        {
             "foo" : ... typed value,
             "bar" : ... typed value
        }],
    }
}
```

The fields are defined as follows:

## BatchDeleteItem fields
<a name="BatchDeleteItem-list"></a>

### BatchDeleteItem fields list
<a name="BatchDeleteItem-list-col"></a>

** `version` **  
The template definition version. Only `2018-05-29` is supported. This value is required.

** `operation` **  
The DynamoDB operation to perform. To perform the `BatchDeleteItem` DynamoDB operation, this must be set to `BatchDeleteItem`. This value is required.

** `tables` **  
The DynamoDB tables to delete the items from. Each table is a list of DynamoDB keys representing the primary key of the items to delete. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). At least one table must be provided. The `tables` value is required.

Things to remember:
+ Contrary to the `DeleteItem` operation, the fully deleted item isn’t returned in the response. Only the passed key is returned.
+ If an item has not been deleted from the table, a *null* element appears in the data block for that table.
+ Invocation results are sorted per table, based on the order in which they were provided inside the request mapping template.
+ Each `Delete` command inside a `BatchDeleteItem` is atomic. However a batch can be partially processed. If a batch is partially processed due to an error, the unprocessed keys are returned as part of the invocation result inside the *unprocessedKeys* block.
+  `BatchDeleteItem` is limited to 25 keys.
+ This operation **is not** supported when used with conflict detection. Using both at the same time may result in an error.

For the following example request mapping template:

```
{
  "version": "2018-05-29",
  "operation": "BatchDeleteItem",
  "tables": {
    "authors": [
        {
          "author_id": {
            "S": "a1"
          }
        },
    ],
    "posts": [
        {
          "author_id": {
            "S": "a1"
          },
          "post_id": {
            "S": "p2"
          }
        }
    ],
  }
}
```

The invocation result available in `$ctx.result` is as follows:

```
{
   "data": {
     "authors": [null],
     "posts": [
        # Was deleted
        {
          "author_id": "a1",
          "post_id": "p2"
        }
     ]
   },
   "unprocessedKeys": {
     "authors": [
        # This key was not processed due to an error
        {
          "author_id": "a1"
        }
      ],
     "posts": []
   }
}
```

The `$ctx.error` contains details about the error. The keys **data**, **unprocessedKeys**, and each table key that was provided in the request mapping template are guaranteed to be present in the invocation result. Items that have been deleted are present in the **data** block. Items that haven’t been processed are marked as *null* inside the data block and are placed inside the **unprocessedKeys** block.

For a more complete example, follow the DynamoDB Batch tutorial with AppSync here [Tutorial: DynamoDB batch resolvers](tutorial-dynamodb-batch.md#aws-appsync-tutorial-dynamodb-batch).

# BatchPutItem
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-batch-put-item"></a>

The `BatchPutItem` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `BatchWriteItem` request to DynamoDB to put multiple items, potentially across multiple tables. For this request template, you must specify the following:
+ The table names where to put the items in
+ The full items to put in each table

The DynamoDB `BatchWriteItem` limits apply and **no condition expression** can be provided.

The `BatchPutItem` mapping document has the following structure:

```
{
    "version" : "2018-05-29",
    "operation" : "BatchPutItem",
    "tables" : {
        "table1": [
        ## Item to put
        {
             "foo" : ... typed value,
             "bar" : ... typed value
        },
        ## Item2 to put
        {
             "foo" : ... typed value,
             "bar" : ... typed value
        }],
        "table2": [
        ## Item3 to put
        {
             "foo" : ... typed value,
             "bar" : ... typed value
        },
        ## Item4 to put
        {
             "foo" : ... typed value,
             "bar" : ... typed value
        }],
    }
}
```

The fields are defined as follows:

## BatchPutItem fields
<a name="BatchPutItem-list"></a>

### BatchPutItem fields list
<a name="BatchPutItem-list-col"></a>

** `version` **  
The template definition version. Only `2018-05-29` is supported. This value is required.

** `operation` **  
The DynamoDB operation to perform. To perform the `BatchPutItem` DynamoDB operation, this must be set to `BatchPutItem`. This value is required.

** `tables` **  
The DynamoDB tables to put the items in. Each table entry represents a list of DynamoDB items to insert for this specific table. At least one table must be provided. This value is required.

Things to remember:
+ The fully inserted items are returned in the response, if successful.
+ If an item hasn’t been inserted in the table, a *null* element is displayed in the data block for that table.
+ The inserted items are sorted per table, based on the order in which they were provided inside the request mapping template.
+ Each `Put` command inside a `BatchPutItem` is atomic, however, a batch can be partially processed. If a batch is partially processed due to an error, the unprocessed keys are returned as part of the invocation result inside the *unprocessedKeys* block.
+  `BatchPutItem` is limited to 25 items.
+ This operation **is not** supported when used with conflict detection. Using both at the same time may result in an error.

For the following example request mapping template:

```
{
  "version": "2018-05-29",
  "operation": "BatchPutItem",
  "tables": {
    "authors": [
        {
          "author_id": {
            "S": "a1"
          },
          "author_name": {
            "S": "a1_name"
          }
        },
    ],
    "posts": [
        {
          "author_id": {
            "S": "a1"
          },
          "post_id": {
            "S": "p2"
          },
          "post_title": {
            "S": "title"
          }
        }
    ],
  }
}
```

The invocation result available in `$ctx.result` is as follows:

```
{
   "data": {
     "authors": [
         null
     ],
     "posts": [
        # Was inserted
        {
          "author_id": "a1",
          "post_id": "p2",
          "post_title": "title"
        }
     ]
   },
   "unprocessedItems": {
     "authors": [
        # This item was not processed due to an error
        {
          "author_id": "a1",
          "author_name": "a1_name"
        }
      ],
     "posts": []
   }
}
```

The `$ctx.error` contains details about the error. The keys **data**, **unprocessedItems**, and each table key that was provided in the request mapping template are guaranteed to be present in the invocation result. Items that have been inserted are in the **data** block. Items that haven’t been processed are marked as *null* inside the data block and are placed inside the **unprocessedItems** block.

For a more complete example, follow the DynamoDB Batch tutorial with AppSync here [Tutorial: DynamoDB batch resolvers](tutorial-dynamodb-batch.md#aws-appsync-tutorial-dynamodb-batch).

# TransactGetItems
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-transact-get-items"></a>

The `TransactGetItems` request mapping document lets you to tell the AWS AppSync DynamoDB resolver to make a `TransactGetItems` request to DynamoDB to retrieve multiple items, potentially across multiple tables. For this request template, you must specify the following:
+ The table name of each request item where to retrieve the item from
+ The key of each request item to retrieve from each table

The DynamoDB `TransactGetItems` limits apply and **no condition expression** can be provided.

The `TransactGetItems` mapping document has the following structure:

```
{
    "version": "2018-05-29",
    "operation": "TransactGetItems",
    "transactItems": [
       ## First request item
       {
           "table": "table1",
           "key": {
               "foo": ... typed value,
               "bar": ... typed value
           },
           "projection" : {
                ...
           }
       },
       ## Second request item
       {
           "table": "table2",
           "key": {
               "foo": ... typed value,
               "bar": ... typed value
           },
           "projection" : {
                ...
           }
       }
    ]
}
```

The fields are defined as follows:

## TransactGetItems fields
<a name="TransactGetItems-list"></a>

### TransactGetItems fields list
<a name="TransactGetItems-list-col"></a>

** `version` **  
The template definition version. Only `2018-05-29` is supported. This value is required.

** `operation` **  
The DynamoDB operation to perform. To perform the `TransactGetItems` DynamoDB operation, this must be set to `TransactGetItems`. This value is required.

** `transactItems` **  
The request items to include. The value is an array of request items. At least one request item must be provided. This `transactItems` value is required.    
** `table` **  
The DynamoDB table to retrieve the item from. The value is a string of the table name. This `table` value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to retrieve. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md).  
**`projection`**  
A projection that's used to specify the attributes to return from the DynamoDB operation. For more information about projections, see [Projections](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-projections). This field is optional.

Things to remember:
+ If a transaction succeeds, the order of retrieved items in the `items` block will be the same as the order of request items.
+ Transactions are performed in an all-or-nothing way. If any request item causes an error, the whole transaction will not be performed and error details will be returned.
+ A request item being unable to be retrieved is not an error. Instead, a *null* element appears in the *items* block in the corresponding position.
+ If the error of a transaction is *TransactionCanceledException*, the `cancellationReasons` block will be populated. The order of cancellation reasons in `cancellationReasons` block will be the same as the order of request items.
+  `TransactGetItems` is limited to 100 request items.

For the following example request mapping template:

```
{
    "version": "2018-05-29",
    "operation": "TransactGetItems",
    "transactItems": [
       ## First request item
       {
           "table": "posts",
           "key": {
               "post_id": {
                 "S": "p1"
               }
           }
       },
       ## Second request item
       {
           "table": "authors",
           "key": {
               "author_id": {
                 "S": a1
               }
           }
       }
    ]
}
```

If the transaction succeeds and only the first requested item is retrieved, the invocation result available in `$ctx.result` is as follows:

```
{
    "items": [
       {
           // Attributes of the first requested item
           "post_id": "p1",
           "post_title": "title",
           "post_description": "description"
       },
       // Could not retrieve the second requested item
       null,
    ],
    "cancellationReasons": null
}
```

If the transaction fails due to *TransactionCanceledException* caused by the first request item, the invocation result available in `$ctx.result` is as follows:

```
{
    "items": null,
    "cancellationReasons": [
       {
           "type":"Sample error type",
           "message":"Sample error message"
       },
       {
           "type":"None",
           "message":"None"
       }
    ]
}
```

The `$ctx.error` contains details about the error. The keys **items** and **cancellationReasons** are guaranteed to be present in `$ctx.result`.

For a more complete example, follow the DynamoDB Transaction tutorial with AppSync here [Tutorial: DynamoDB transaction resolvers](tutorial-dynamodb-transact.md#aws-appsync-tutorial-dynamodb-transact).

# TransactWriteItems
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-transact-write-items"></a>

The `TransactWriteItems` request mapping document lets you tell the AWS AppSync DynamoDB resolver to make a `TransactWriteItems` request to DynamoDB to write multiple items, potentially to multiple tables. For this request template, you must specify the following:
+ The destination table name of each request item
+ The operation of each request item to perform. There are four types of operations that are supported: *PutItem*, *UpdateItem*, *DeleteItem*, and *ConditionCheck* 
+ The key of each request item to write

The DynamoDB `TransactWriteItems` limits apply.

The `TransactWriteItems` mapping document has the following structure:

```
{
    "version": "2018-05-29",
    "operation": "TransactWriteItems",
    "transactItems": [
       {
           "table": "table1",
           "operation": "PutItem",
           "key": {
               "foo": ... typed value,
               "bar": ... typed value
           },
           "attributeValues": {
               "baz": ... typed value
           },
           "condition": {
               "expression": "someExpression",
               "expressionNames": {
                   "#foo": "foo"
               },
               "expressionValues": {
                   ":bar": ... typed value
               },
               "returnValuesOnConditionCheckFailure": true|false
           }
       },
       {
           "table":"table2",
           "operation": "UpdateItem",
           "key": {
               "foo": ... typed value,
               "bar": ... typed value
           },
           "update": {
               "expression": "someExpression",
               "expressionNames": {
                   "#foo": "foo"
               },
               "expressionValues": {
                   ":bar": ... typed value
               }
           },
           "condition": {
               "expression": "someExpression",
               "expressionNames": {
                   "#foo":"foo"
               },
               "expressionValues": {
                   ":bar": ... typed value
               },
               "returnValuesOnConditionCheckFailure": true|false
           }
       },
       {
           "table": "table3",
           "operation": "DeleteItem",
           "key":{
               "foo": ... typed value,
               "bar": ... typed value
           },
           "condition":{
               "expression": "someExpression",
               "expressionNames": {
                   "#foo": "foo"
               },
               "expressionValues": {
                   ":bar": ... typed value
               },
               "returnValuesOnConditionCheckFailure": true|false
           }
       },
       {
           "table": "table4",
           "operation": "ConditionCheck",
           "key":{
               "foo": ... typed value,
               "bar": ... typed value
           },
           "condition":{
               "expression": "someExpression",
               "expressionNames": {
                   "#foo": "foo"
               },
               "expressionValues": {
                   ":bar": ... typed value
               },
               "returnValuesOnConditionCheckFailure": true|false
           }
       }
    ]
}
```

## TransactWriteItems fields
<a name="TransactWriteItems-list"></a>

### TransactWriteItems fields list
<a name="TransactWriteItems-list-col"></a>

**The fields are defined as follows:**    
** `version` **  
The template definition version. Only `2018-05-29` is supported. This value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `TransactWriteItems` DynamoDB operation, this must be set to `TransactWriteItems`. This value is required.  
** `transactItems` **  
The request items to include. The value is an array of request items. At least one request item must be provided. This `transactItems` value is required.  
For `PutItem`, the fields are defined as follows:    
** `table` **  
The destination DynamoDB table. The value is a string of the table name. This `table` value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `PutItem` DynamoDB operation, this must be set to `PutItem`. This value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to put. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required.  
** `attributeValues` **  
The rest of the attributes of the item to be put into DynamoDB. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This field is optional.  
** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `PutItem` request overwrites any existing entry for that item. You can specify whether to retrieve the existing item back when condition check fails. For more information about transactional conditions, see [Transaction condition expressions](aws-appsync-resolver-mapping-template-reference-dynamodb-transaction-condition-expressions.md). This value is optional.
For `UpdateItem`, the fields are defined as follows:    
** `table` **  
The DynamoDB table to update. The value is a string of the table name. This `table` value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `UpdateItem` DynamoDB operation, this must be set to `UpdateItem`. This value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to update. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required.  
** `update` **  
The `update` section lets you specify an update expression that describes how to update the item in DynamoDB. For more information about how to write update expressions, see the [DynamoDB UpdateExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html). This section is required.  
** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `UpdateItem` request updates the existing entry regardless of its current state. You can specify whether to retrieve the existing item back when condition check fails. For more information about transactional conditions, see [Transaction condition expressions](aws-appsync-resolver-mapping-template-reference-dynamodb-transaction-condition-expressions.md). This value is optional.
For `DeleteItem`, the fields are defined as follows:    
** `table` **  
The DynamoDB table in which to delete the item. The value is a string of the table name. This `table` value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `DeleteItem` DynamoDB operation, this must be set to `DeleteItem`. This value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to delete. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required.  
** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. If no condition is specified, the `DeleteItem` request deletes an item regardless of its current state. You can specify whether to retrieve the existing item back when condition check fails. For more information about transactional conditions, see [Transaction condition expressions](aws-appsync-resolver-mapping-template-reference-dynamodb-transaction-condition-expressions.md). This value is optional.
For `ConditionCheck`, the fields are defined as follows:    
** `table` **  
The DynamoDB table in which to check the condition. The value is a string of the table name. This `table` value is required.  
** `operation` **  
The DynamoDB operation to perform. To perform the `ConditionCheck` DynamoDB operation, this must be set to `ConditionCheck`. This value is required.  
** `key` **  
The DynamoDB key representing the primary key of the item to condition check. DynamoDB items may have a single hash key, or a hash key and sort key, depending on the table structure. For more information about how to specify a “typed value”, see [Type system (request mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This value is required.  
** `condition` **  
A condition to determine if the request should succeed or not, based on the state of the object already in DynamoDB. You can specify whether to retrieve the existing item back when condition check fails. For more information about transactional conditions, see [Transaction condition expressions](aws-appsync-resolver-mapping-template-reference-dynamodb-transaction-condition-expressions.md). This value is required.

Things to remember:
+ Only keys of request items are returned in the response, if successful. The order of keys will be the same as the order of request items.
+ Transactions are performed in an all-or-nothing way. If any request item causes an error, the whole transaction will not be performed and error details will be returned.
+ No two request items can target the same item. Otherwise they will cause *TransactionCanceledException* error.
+ If the error of a transaction is *TransactionCanceledException*, the `cancellationReasons` block will be populated. If a request item’s condition check fails **and** you did not specify `returnValuesOnConditionCheckFailure` to be `false`, the item existing in the table will be retrieved and stored in `item` at the corresponding position of `cancellationReasons` block.
+  `TransactWriteItems` is limited to 100 request items.
+ This operation **is not** supported when used with conflict detection. Using both at the same time may result in an error.

For the following example request mapping template:

```
{
    "version": "2018-05-29",
    "operation": "TransactWriteItems",
    "transactItems": [
       {
           "table": "posts",
           "operation": "PutItem",
           "key": {
               "post_id": {
                   "S": "p1"
               }
           },
           "attributeValues": {
               "post_title": {
                   "S": "New title"
               },
               "post_description": {
                   "S": "New description"
               }
           },
           "condition": {
               "expression": "post_title = :post_title",
               "expressionValues": {
                   ":post_title": {
                       "S": "Expected old title"
                   }
               }
           }
       },
       {
           "table":"authors",
           "operation": "UpdateItem",
           "key": {
               "author_id": {
                   "S": "a1"
               },
           },
           "update": {
               "expression": "SET author_name = :author_name",
               "expressionValues": {
                   ":author_name": {
                       "S": "New name"
                   }
               }
           },
       }
    ]
}
```

If the transaction succeeds, the invocation result available in `$ctx.result` is as follows:

```
{
    "keys": [
       // Key of the PutItem request
       {
           "post_id": "p1",
       },
       // Key of the UpdateItem request
       {
           "author_id": "a1"
       }
    ],
    "cancellationReasons": null
}
```

If the transaction fails due to condition check failure of the `PutItem` request, the invocation result available in `$ctx.result` is as follows:

```
{
    "keys": null,
    "cancellationReasons": [
       {
           "item": {
               "post_id": "p1",
               "post_title": "Actual old title",
               "post_description": "Old description"
           },
           "type": "ConditionCheckFailed",
           "message": "The condition check failed."
       },
       {
           "type": "None",
           "message": "None"
       }
    ]
}
```

The `$ctx.error` contains details about the error. The keys **keys** and **cancellationReasons** are guaranteed to be present in `$ctx.result`.

For a more complete example, follow the DynamoDB Transaction tutorial with AppSync here [Tutorial: DynamoDB transaction resolvers](tutorial-dynamodb-transact.md#aws-appsync-tutorial-dynamodb-transact).

# Type system (request mapping)
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request"></a>

When using the AWS AppSync DynamoDB resolver to call your DynamoDB tables, AWS AppSync needs to know the type of each value to use in that call. This is because DynamoDB supports more type primitives than GraphQL or JSON (such as sets and binary data). AWS AppSync needs some hints when translating between GraphQL and DynamoDB, otherwise it would have to make some assumptions on how data is structured in your table.

For more information about DynamoDB data types, see the DynamoDB [Data type descriptors](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.LowLevelAPI.html#Programming.LowLevelAPI.DataTypeDescriptors) and [Data types](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes) documentation.

A DynamoDB value is represented by a JSON object containing a single key-value pair. The key specifies the DynamoDB type, and the value specifies the value itself. In the following example, the key `S` denotes that the value is a string, and the value `identifier` is the string value itself.

```
{ "S" : "identifier" }
```

Note that the JSON object cannot have more than one key-value pair. If more than one key-value pair is specified, the request mapping document isn’t parsed.

A DynamoDB value is used anywhere in a request mapping document where you need to specify a value. Some places where you need to do this include: `key` and `attributeValue` sections, and the `expressionValues` section of expression sections. In the following example, the DynamoDB String value `identifier` is being assigned to the `id` field in a `key` section (perhaps in a `GetItem` request mapping document).

```
"key" : {
   "id" : { "S" : "identifier" }
}
```

 **Supported Types** 

AWS AppSync supports the following DynamoDB scalar, document, and set types:

**String type `S` **  
A single string value. A DynamoDB String value is denoted by:  

```
{ "S" : "some string" }
```
An example usage is:  

```
"key" : {
   "id" : { "S" : "some string" }
}
```

**String set type `SS` **  
A set of string values. A DynamoDB String Set value is denoted by:  

```
{ "SS" : [ "first value", "second value", ... ] }
```
An example usage is:  

```
"attributeValues" : {
   "phoneNumbers" : { "SS" : [ "+1 555 123 4567", "+1 555 234 5678" ] }
}
```

**Number type `N` **  
A single numeric value. A DynamoDB Number value is denoted by:  

```
{ "N" : 1234 }
```
An example usage is:  

```
"expressionValues" : {
   ":expectedVersion" : { "N" : 1 }
}
```

**Number set type `NS` **  
A set of number values. A DynamoDB Number Set value is denoted by:  

```
{ "NS" : [ 1, 2.3, 4 ... ] }
```
An example usage is:  

```
"attributeValues" : {
   "sensorReadings" : { "NS" : [ 67.8, 12.2, 70 ] }
}
```

**Binary type `B` **  
A binary value. A DynamoDB Binary value is denoted by:  

```
{ "B" : "SGVsbG8sIFdvcmxkIQo=" }
```
Note that the value is actually a string, where the string is the base64-encoded representation of the binary data. AWS AppSync decodes this string back into its binary value before sending it to DynamoDB. AWS AppSync uses the base64 decoding scheme as defined by RFC 2045: any character that isn’t in the base64 alphabet is ignored.  
An example usage is:  

```
"attributeValues" : {
   "binaryMessage" : { "B" : "SGVsbG8sIFdvcmxkIQo=" }
}
```

**Binary set type `BS` **  
A set of binary values. A DynamoDB Binary Set value is denoted by:  

```
{ "BS" : [ "SGVsbG8sIFdvcmxkIQo=", "SG93IGFyZSB5b3U/Cg==" ... ] }
```
Note that the value is actually a string, where the string is the base64-encoded representation of the binary data. AWS AppSync decodes this string back into its binary value before sending it to DynamoDB. AWS AppSync uses the base64 decoding scheme as defined by RFC 2045: any character that is not in the base64 alphabet is ignored.  
An example usage is:  

```
"attributeValues" : {
   "binaryMessages" : { "BS" : [ "SGVsbG8sIFdvcmxkIQo=", "SG93IGFyZSB5b3U/Cg==" ] }
}
```

**Boolean type `BOOL` **  
A Boolean value. A DynamoDB Boolean value is denoted by:  

```
{ "BOOL" : true }
```
Note that only `true` and `false` are valid values.  
An example usage is:  

```
"attributeValues" : {
   "orderComplete" : { "BOOL" : false }
}
```

**List type `L` **  
A list of any other supported DynamoDB value. A DynamoDB List value is denoted by:  

```
{ "L" : [ ... ] }
```
Note that the value is a compound value, where the list can contain zero or more of any supported DynamoDB value (including other lists). The list can also contain a mix of different types.  
An example usage is:  

```
{ "L" : [
      { "S"  : "A string value" },
      { "N"  : 1 },
      { "SS" : [ "Another string value", "Even more string values!" ] }
   ]
}
```

**Map type `M` **  
Representing an unordered collection of key-value pairs of other supported DynamoDB values. A DynamoDB Map value is denoted by:  

```
{ "M" : { ... } }
```
Note that a map can contain zero or more key-value pairs. The key must be a string, and the value can be any supported DynamoDB value (including other maps). The map can also contain a mix of different types.  
An example usage is:  

```
{ "M" : {
      "someString" : { "S"  : "A string value" },
      "someNumber" : { "N"  : 1 },
      "stringSet"  : { "SS" : [ "Another string value", "Even more string values!" ] }
   }
}
```

**Null type `NULL` **  
A null value. A DynamoDB Null value is denoted by:  

```
{ "NULL" : null }
```
An example usage is:  

```
"attributeValues" : {
   "phoneNumbers" : { "NULL" : null }
}
```

For more information about each type, see the [DynamoDB documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html) .

# Type system (response mapping)
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-responses"></a>

When receiving a response from DynamoDB, AWS AppSync automatically converts it into GraphQL and JSON primitive types. Each attribute in DynamoDB is decoded and returned in the response mapping context.

For example, if DynamoDB returns the following:

```
{
    "id" : { "S" : "1234" },
    "name" : { "S" : "Nadia" },
    "age" : { "N" : 25 }
}
```

Then the AWS AppSync DynamoDB resolver converts it into GraphQL and JSON types as:

```
{
    "id" : "1234",
    "name" : "Nadia",
    "age" : 25
}
```

This section explains how AWS AppSync converts the following DynamoDB scalar, document, and set types:

**String type `S` **  
A single string value. A DynamoDB String value is returned as a string.  
For example, if DynamoDB returned the following DynamoDB String value:  

```
{ "S" : "some string" }
```
AWS AppSync converts it to a string:  

```
"some string"
```

**String set type `SS` **  
A set of string values. A DynamoDB String Set value is returned as a list of strings.  
For example, if DynamoDB returned the following DynamoDB String Set value:  

```
{ "SS" : [ "first value", "second value", ... ] }
```
AWS AppSync converts it to a list of strings:  

```
[ "+1 555 123 4567", "+1 555 234 5678" ]
```

**Number type `N` **  
A single numeric value. A DynamoDB Number value is returned as a number.  
For example, if DynamoDB returned the following DynamoDB Number value:  

```
{ "N" : 1234 }
```
AWS AppSync converts it to a number:  

```
1234
```

**Number set type `NS` **  
A set of number values. A DynamoDB Number Set value is returned as a list of numbers.  
For example, if DynamoDB returned the following DynamoDB Number Set value:  

```
{ "NS" : [ 67.8, 12.2, 70 ] }
```
AWS AppSync converts it to a list of numbers:  

```
[ 67.8, 12.2, 70 ]
```

**Binary type `B` **  
A binary value. A DynamoDB Binary value is returned as a string containing the base64 representation of that value.  
For example, if DynamoDB returned the following DynamoDB Binary value:  

```
{ "B" : "SGVsbG8sIFdvcmxkIQo=" }
```
AWS AppSync converts it to a string containing the base64 representation of the value:  

```
"SGVsbG8sIFdvcmxkIQo="
```
Note that the binary data is encoded in the base64 encoding scheme as specified in [RFC 4648](https://tools.ietf.org/html/rfc4648) and [RFC 2045](https://tools.ietf.org/html/rfc2045).

**Binary set type `BS` **  
A set of binary values. A DynamoDB Binary Set value is returned as a list of strings containing the base64 representation of the values.  
For example, if DynamoDB returned the following DynamoDB Binary Set value:  

```
{ "BS" : [ "SGVsbG8sIFdvcmxkIQo=", "SG93IGFyZSB5b3U/Cg==" ... ] }
```
AWS AppSync converts it to a list of strings containing the base64 representation of the values:  

```
[ "SGVsbG8sIFdvcmxkIQo=", "SG93IGFyZSB5b3U/Cg==" ... ]
```
Note that the binary data is encoded in the base64 encoding scheme as specified in [RFC 4648](https://tools.ietf.org/html/rfc4648) and [RFC 2045](https://tools.ietf.org/html/rfc2045).

**Boolean type `BOOL` **  
A Boolean value. A DynamoDB Boolean value is returned as a Boolean.  
For example, if DynamoDB returned the following DynamoDB Boolean value:  

```
{ "BOOL" : true }
```
AWS AppSync converts it to a Boolean:  

```
true
```

**List type `L` **  
A list of any other supported DynamoDB value. A DynamoDB List value is returned as a list of values, where each inner value is also converted.  
For example, if DynamoDB returned the following DynamoDB List value:  

```
{ "L" : [
      { "S"  : "A string value" },
      { "N"  : 1 },
      { "SS" : [ "Another string value", "Even more string values!" ] }
   ]
}
```
AWS AppSync converts it to a list of converted values:  

```
[ "A string value", 1, [ "Another string value", "Even more string values!" ] ]
```

**Map type `M` **  
A key/value collection of any other supported DynamoDB value. A DynamoDB Map value is returned as a JSON object, where each key/value is also converted.  
For example, if DynamoDB returned the following DynamoDB Map value:  

```
{ "M" : {
      "someString" : { "S"  : "A string value" },
      "someNumber" : { "N"  : 1 },
      "stringSet"  : { "SS" : [ "Another string value", "Even more string values!" ] }
   }
}
```
AWS AppSync converts it to a JSON object:  

```
{
   "someString" : "A string value",
   "someNumber" : 1,
   "stringSet"  : [ "Another string value", "Even more string values!" ]
}
```

**Null type `NULL` **  
A null value.  
For example, if DynamoDB returned the following DynamoDB Null value:  

```
{ "NULL" : null }
```
AWS AppSync converts it to a null:  

```
null
```

# Filters
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-filter"></a>

When querying objects in DynamoDB using the `Query` and `Scan` operations, you can optionally specify a `filter` that evaluates the results and returns only the desired values.

The filter mapping section of a `Query` or `Scan` mapping document has the following structure:

```
"filter" : {
    "expression" : "filter expression"
    "expressionNames" : {
        "#name" : "name",
    },
    "expressionValues" : {
        ":value" : ... typed value
    },
}
```

The fields are defined as follows:

** `expression` **  
The query expression. For more information about how to write filter expressions, see the [DynamoDB QueryFilter](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.QueryFilter.html) and [DynamoDB ScanFilter](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.ScanFilter.html) documentation. This field must be specified.

** `expressionNames` **  
The substitutions for expression attribute *name* placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the `expression`. The value must be a string that corresponds to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the `expression`.

** `expressionValues` **  
The substitutions for expression attribute *value* placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the `expression`, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type System (Request Mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This must be specified. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the `expression`.

## Example
<a name="id18"></a>

The following example is a filter section for a mapping template, where entries retrieved from DynamoDB are only returned if the title starts with the `title` argument.

```
"filter" : {
    "expression" : "begins_with(#title, :title)",
    "expressionNames" : {
        "#title" : "title"
    },
    "expressionValues" : {
        ":title" : $util.dynamodb.toDynamoDBJson($context.arguments.title)
    }
}
```

# Condition expressions
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-condition-expressions"></a>

When you mutate objects in DynamoDB by using the `PutItem`, `UpdateItem`, and `DeleteItem` DynamoDB operations, you can optionally specify a condition expression that controls whether the request should succeed or not, based on the state of the object already in DynamoDB before the operation is performed.

The AWS AppSync DynamoDB resolver allows a condition expression to be specified in `PutItem`, `UpdateItem`, and `DeleteItem` request mapping documents, and also a strategy to follow if the condition fails and the object was not updated.

## Example 1
<a name="id19"></a>

The following `PutItem` mapping document doesn’t have a condition expression. As a result, it puts an item in DynamoDB even if an item with the same key already exists, thereby overwriting the existing item.

```
{
   "version" : "2017-02-28",
   "operation" : "PutItem",
   "key" : {
      "id" : { "S" : "1" }
   }
}
```

## Example 2
<a name="id20"></a>

The following `PutItem` mapping document does have a condition expression that allows the operation succeed only if an item with the same key does *not* exist in DynamoDB.

```
{
   "version" : "2017-02-28",
   "operation" : "PutItem",
   "key" : {
      "id" : { "S" : "1" }
   },
   "condition" : {
      "expression" : "attribute_not_exists(id)"
   }
}
```

By default, if the condition check fails, the AWS AppSync DynamoDB resolver returns an error for the mutation. However, the AWS AppSync DynamoDB resolver offers some additional features to help developers handle some common edge cases:
+ If AWS AppSync DynamoDB resolver can determine that the current value in DynamoDB matches the desired result, it treats the operation as if it succeeded anyway.
+ Instead of returning an error, you can configure the resolver to invoke a custom Lambda function to decide how the AWS AppSync DynamoDB resolver should handle the failure.

These are described in greater detail in the [Handling a Condition Check Failure](#aws-appsync-resolver-mapping-template-reference-dynamodb-condition-handling) section.

For more information about DynamoDB conditions expressions, see the [DynamoDB ConditionExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html) .

## Specifying a condition
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-condition-specification"></a>

The `PutItem`, `UpdateItem`, and `DeleteItem` request mapping documents all allow an optional `condition` section to be specified. If omitted, no condition check is made. If specified, the condition must be true for the operation to succeed.

A `condition` section has the following structure:

```
"condition" : {
    "expression" : "someExpression"
    "expressionNames" : {
        "#foo" : "foo"
    },
    "expressionValues" : {
        ":bar" : ... typed value
    },
    "equalsIgnore" : [ "version" ],
    "consistentRead" : true,
    "conditionalCheckFailedHandler" : {
        "strategy" : "Custom",
        "lambdaArn" : "arn:..."
    }
}
```

The following fields specify the condition:

** `expression` **  
The update expression itself. For more information about how to write condition expressions, see the [DynamoDB ConditionExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html) . This field must be specified.

** `expressionNames` **  
The substitutions for expression attribute name placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the *expression*, and the value must be a string corresponding to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the *expression*.

** `expressionValues` **  
The substitutions for expression attribute value placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the expression, and the value must be a typed value. For more information about how to specify a “typed value”, see [Type System (Request Mapping)](aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request.md). This must be specified. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the expression.

The remaining fields tell the AWS AppSync DynamoDB resolver how to handle a condition check failure:

** `equalsIgnore` **  
When a condition check fails when using the `PutItem` operation, the AWS AppSync DynamoDB resolver compares the item currently in DynamoDB against the item it tried to write. If they are the same, it treats the operation as it if succeeded anyway. You can use the `equalsIgnore` field to specify a list of attributes that AWS AppSync should ignore when performing that comparison. For example, if the only difference was a `version` attribute, it treats the operation as if it succeeded. This field is optional.

** `consistentRead` **  
When a condition check fails, AWS AppSync gets the current value of the item from DynamoDB using a strongly consistent read. You can use this field to tell the AWS AppSync DynamoDB resolver to use an eventually consistent read instead. This field is optional, and defaults to `true`.

** `conditionalCheckFailedHandler` **  
This section allows you to specify how the AWS AppSync DynamoDB resolver treats a condition check failure after it has compared the current value in DynamoDB against the expected result. This section is optional. If omitted, it defaults to a strategy of `Reject`.    
** `strategy` **  
The strategy the AWS AppSync DynamoDB resolver takes after it has compared the current value in DynamoDB against the expected result. This field is required and has the following possible values:    
** `Reject` **  
The mutation fails, and an error is added to the GraphQL response.  
** `Custom` **  
The AWS AppSync DynamoDB resolver invokes a custom Lambda function to decide how to handle the condition check failure. When the `strategy` is set to `Custom`, the `lambdaArn` field must contain the ARN of the Lambda function to invoke.  
** `lambdaArn` **  
The ARN of the Lambda function to invoke that determines how the AWS AppSync DynamoDB resolver should handle the condition check failure. This field must only be specified when `strategy` is set to `Custom`. For more information about how to use this feature, see [Handling a Condition Check Failure](#aws-appsync-resolver-mapping-template-reference-dynamodb-condition-handling).

## Handling a condition check failure
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-condition-handling"></a>

By default, when a condition check fails, the AWS AppSync DynamoDB resolver returns an error for the mutation and the current value of the object in DynamoDB. However, the AWS AppSync DynamoDB resolver offers some additional features to help developers handle some common edge cases:
+ If AWS AppSync DynamoDB resolver can determine that the current value in DynamoDB matches the desired result, it treats the operation as if it succeeded anyway.
+ Instead of returning an error, you can configure the resolver to invoke a custom Lambda function to decide how the AWS AppSync DynamoDB resolver should handle the failure.

The flowchart for this process is:

![\[Flowchart showing process for transforming requests with mutation attempts and value checks.\]](http://docs.aws.amazon.com/appsync/latest/devguide/images/DynamoDB-condition-check-failure-handling.png)


### Checking for the desired result
<a name="checking-for-the-desired-result"></a>

When the condition check fails, the AWS AppSync DynamoDB resolver performs a `GetItem` DynamoDB request to get the current value of the item from DynamoDB. By default, it uses a strongly consistent read, however this can be configured using the `consistentRead` field in the `condition` block and compare it against the expected result:
+ For the `PutItem` operation, the AWS AppSync DynamoDB resolver compares the current value against the one it attempted to write, excluding any attributes listed in `equalsIgnore` from the comparison. If the items are the same, it treats the operation as successful and returns the item that was retrieved from DynamoDB. Otherwise, it follows the configured strategy.

  For example, if the `PutItem` request mapping document looked like the following:

  ```
  {
     "version" : "2017-02-28",
     "operation" : "PutItem",
     "key" : {
        "id" : { "S" : "1" }
     },
     "attributeValues" : {
        "name" : { "S" : "Steve" },
        "version" : { "N" : 2 }
     },
     "condition" : {
        "expression" : "version = :expectedVersion",
        "expressionValues" : {
            ":expectedVersion" : { "N" : 1 }
        },
        "equalsIgnore": [ "version" ]
     }
  }
  ```

  And the item currently in DynamoDB looked like the following:

  ```
  {
     "id" : { "S" : "1" },
     "name" : { "S" : "Steve" },
     "version" : { "N" : 8 }
  }
  ```

  The AWS AppSync DynamoDB resolver would compare the item it tried to write against the current value, see that the only difference was the `version` field, but because it’s configured to ignore the `version` field, it treats the operation as successful and returns the item that was retrieved from DynamoDB.
+ For the `DeleteItem` operation, the AWS AppSync DynamoDB resolver checks to verify that an item was returned from DynamoDB. If no item was returned, it treats the operation as successful. Otherwise, it follows the configured strategy.
+ For the `UpdateItem` operation, the AWS AppSync DynamoDB resolver does not have enough information to determine if the item currently in DynamoDB matches the expected result, and therefore follows the configured strategy.

If the current state of the object in DynamoDB is different from the expected result, the AWS AppSync DynamoDB resolver follows the configured strategy, to either reject the mutation or invoke a Lambda function to determine what to do next.

### Following the “reject” strategy
<a name="following-the-reject-strategy"></a>

When following the `Reject` strategy, the AWS AppSync DynamoDB resolver returns an error for the mutation.

For example, given the following mutation request:

```
mutation {
    updatePerson(id: 1, name: "Steve", expectedVersion: 1) {
        Name
        theVersion
    }
}
```

If the item returned from DynamoDB looks like the following:

```
{
   "id" : { "S" : "1" },
   "name" : { "S" : "Steve" },
   "version" : { "N" : 8 }
}
```

And the response mapping template looks like the following:

```
{
   "id" : $util.toJson($context.result.id),
   "Name" : $util.toJson($context.result.name),
   "theVersion" : $util.toJson($context.result.version)
}
```

The GraphQL response looks like the following:

```
{
  "data": null,
  "errors": [
    {
      "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)"
      "errorType": "DynamoDB:ConditionalCheckFailedException",
      ...
    }
  ]
}
```

Also, if any fields in the returned object are filled by other resolvers and the mutation had succeeded, they won’t be resolved when the object is returned in the `error` section.

### Following the “custom” strategy
<a name="following-the-custom-strategy"></a>

When following the `Custom` strategy, the AWS AppSync DynamoDB resolver invokes a Lambda function to decide what to do next. The Lambda function chooses one of the following options:
+  `reject` the mutation. This tells the AWS AppSync DynamoDB resolver to behave as if the configured strategy was `Reject`, returning an error for the mutation and the current value of the object in DynamoDB as described in the previous section.
+  `discard` the mutation. This tells the AWS AppSync DynamoDB resolver to silently ignore the condition check failure and returns the value in DynamoDB.
+  `retry` the mutation. This tells the AWS AppSync DynamoDB resolver to retry the mutation with a new request mapping document.

 **The Lambda invocation request** 

The AWS AppSync DynamoDB resolver invokes the Lambda function specified in the `lambdaArn`. It uses the same `service-role-arn` configured on the data source. The payload of the invocation has the following structure:

```
{
    "arguments": { ... },
    "requestMapping": {... },
    "currentValue": { ... },
    "resolver": { ... },
    "identity": { ... }
}
```

The fields are defined as follows:

** `arguments` **  
The arguments from the GraphQL mutation. This is the same as the arguments available to the request mapping document in `$context.arguments`.

** `requestMapping` **  
The request mapping document for this operation.

** `currentValue` **  
The current value of the object in DynamoDB.

** `resolver` **  
Information about the AWS AppSync resolver.

** `identity` **  
Information about the caller. This is the same as the identity information available to the request mapping document in `$context.identity`.

A full example of the payload:

```
{
    "arguments": {
        "id": "1",
        "name": "Steve",
        "expectedVersion": 1
    },
    "requestMapping": {
        "version" : "2017-02-28",
        "operation" : "PutItem",
        "key" : {
           "id" : { "S" : "1" }
        },
        "attributeValues" : {
           "name" : { "S" : "Steve" },
           "version" : { "N" : 2 }
        },
        "condition" : {
           "expression" : "version = :expectedVersion",
           "expressionValues" : {
               ":expectedVersion" : { "N" : 1 }
           },
           "equalsIgnore": [ "version" ]
        }
    },
    "currentValue": {
        "id" : { "S" : "1" },
        "name" : { "S" : "Steve" },
        "version" : { "N" : 8 }
    },
    "resolver": {
        "tableName": "People",
        "awsRegion": "us-west-2",
        "parentType": "Mutation",
        "field": "updatePerson",
        "outputType": "Person"
    },
    "identity": {
        "accountId": "123456789012",
        "sourceIp": "x.x.x.x",
        "user": "AIDAAAAAAAAAAAAAAAAAA",
        "userArn": "arn:aws:iam::123456789012:user/appsync"
    }
}
```

 **The Lambda Invocation Response** 

The Lambda function can inspect the invocation payload and apply any business logic to decide how the AWS AppSync DynamoDB resolver should handle the failure. There are three options for handling the condition check failure:
+  `reject` the mutation. The response payload for this option must have this structure:

  ```
  {
      "action": "reject"
  }
  ```

  This tells the AWS AppSync DynamoDB resolver to behave as if the configured strategy was `Reject`, returning an error for the mutation and the current value of the object in DynamoDB, as described in the section above.
+  `discard` the mutation. The response payload for this option must have this structure:

  ```
  {
      "action": "discard"
  }
  ```

  This tells the AWS AppSync DynamoDB resolver to silently ignore the condition check failure and returns the value in DynamoDB.
+  `retry` the mutation. The response payload for this option must have this structure:

  ```
  {
      "action": "retry",
      "retryMapping": { ... }
  }
  ```

  This tells the AWS AppSync DynamoDB resolver to retry the mutation with a new request mapping document. The structure of the `retryMapping` section depends on the DynamoDB operation, and is a subset of the full request mapping document for that operation.

  For `PutItem`, the `retryMapping` section has the following structure. For a description of the `attributeValues` field, see [PutItem](aws-appsync-resolver-mapping-template-reference-dynamodb-putitem.md).

  ```
  {
      "attributeValues": { ... },
      "condition": {
          "equalsIgnore" = [ ... ],
          "consistentRead" = true
      }
  }
  ```

  For `UpdateItem`, the `retryMapping` section has the following structure. For a description of the `update` section, see [UpdateItem](aws-appsync-resolver-mapping-template-reference-dynamodb-updateitem.md).

  ```
  {
      "update" : {
          "expression" : "someExpression"
          "expressionNames" : {
              "#foo" : "foo"
          },
          "expressionValues" : {
              ":bar" : ... typed value
          }
      },
      "condition": {
          "consistentRead" = true
      }
  }
  ```

  For `DeleteItem`, the `retryMapping` section has the following structure.

  ```
  {
      "condition": {
          "consistentRead" = true
      }
  }
  ```

  There is no way to specify a different operation or key to work on. The AWS AppSync DynamoDB resolver only allows retries of the same operation on the same object. Also, the `condition` section doesn’t allow a `conditionalCheckFailedHandler` to be specified. If the retry fails, the AWS AppSync DynamoDB resolver follows the `Reject` strategy.

Here is an example Lambda function to deal with a failed `PutItem` request. The business logic looks at who made the call. If it was made by `jeffTheAdmin`, it retries the request, updating the `version` and `expectedVersion` from the item currently in DynamoDB. Otherwise, it rejects the mutation.

```
exports.handler = (event, context, callback) => {
    console.log("Event: "+ JSON.stringify(event));

    // Business logic goes here.

    var response;
    if ( event.identity.user == "jeffTheAdmin" ) {
        response = {
            "action" : "retry",
            "retryMapping" : {
                "attributeValues" : event.requestMapping.attributeValues,
                "condition" : {
                    "expression" : event.requestMapping.condition.expression,
                    "expressionValues" : event.requestMapping.condition.expressionValues
                }
            }
        }
        response.retryMapping.attributeValues.version = { "N" : event.currentValue.version.N + 1 }
        response.retryMapping.condition.expressionValues[':expectedVersion'] = event.currentValue.version

    } else {
        response = { "action" : "reject" }
    }

    console.log("Response: "+ JSON.stringify(response))
    callback(null, response)
};
```

# Transaction condition expressions
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-transaction-condition-expressions"></a>

Transaction condition expressions are available in request mapping templates of all four types of operations in `TransactWriteItems`, namely, `PutItem`, `DeleteItem`, `UpdateItem`, and `ConditionCheck`.

For `PutItem`, `DeleteItem`, and `UpdateItem`, the transaction condition expression is optional. For `ConditionCheck`, the transaction condition expression is required.

## Example 1
<a name="id22"></a>

The following transactional `DeleteItem` mapping document does not have a condition expression. As a result, it deletes the item in DynamoDB.

```
{
   "version": "2018-05-29",
   "operation": "TransactWriteItems",
   "transactItems": [
      {
         "table": "posts",
         "operation": "DeleteItem",
         "key": {
            "id": { "S" : "1" }
         }
      }
   ]
}
```

## Example 2
<a name="id23"></a>

The following transactional `DeleteItem` mapping document does have a transaction condition expression that allows the operation succeed only if the author of that post equals a certain name.

```
{
   "version": "2018-05-29",
   "operation": "TransactWriteItems",
   "transactItems": [
      {
         "table": "posts",
         "operation": "DeleteItem",
         "key": {
            "id": { "S" : "1" }
         }
         "condition": {
            "expression": "author = :author",
            "expressionValues": {
               ":author": { "S" : "Chunyan" }
            }
         }
      }
   ]
}
```

If the condition check fails, it will cause `TransactionCanceledException` and the error detail will be returned in `$ctx.result.cancellationReasons`. Note that by default, the old item in DynamoDB that made condition check fail will be returned in `$ctx.result.cancellationReasons`.

## Specifying a condition
<a name="id24"></a>

The `PutItem`, `UpdateItem`, and `DeleteItem` request mapping documents all allow an optional `condition` section to be specified. If omitted, no condition check is made. If specified, the condition must be true for the operation to succeed. The `ConditionCheck` must have a `condition` section to be specified. The condition must be true for the whole transaction to succeed.

A `condition` section has the following structure:

```
"condition": {
    "expression": "someExpression",
    "expressionNames": {
        "#foo": "foo"
    },
    "expressionValues": {
        ":bar": ... typed value
    },
    "returnValuesOnConditionCheckFailure": false
}
```

The following fields specify the condition:

** `expression` **  
The update expression itself. For more information about how to write condition expressions, see the [DynamoDB ConditionExpressions documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html) . This field must be specified.

** `expressionNames` **  
The substitutions for expression attribute name placeholders, in the form of key-value pairs. The key corresponds to a name placeholder used in the *expression*, and the value must be a string corresponding to the attribute name of the item in DynamoDB. This field is optional, and should only be populated with substitutions for expression attribute name placeholders used in the *expression*.

** `expressionValues` **  
The substitutions for expression attribute value placeholders, in the form of key-value pairs. The key corresponds to a value placeholder used in the expression, and the value must be a typed value. For more information about how to specify a “typed value”, see Type System (request mapping). This must be specified. This field is optional, and should only be populated with substitutions for expression attribute value placeholders used in the expression.

** `returnValuesOnConditionCheckFailure` **  
Specify whether to retrieve the item in DynamoDB back when a condition check fails. The retrieved item will be in `$ctx.result.cancellationReasons[$index].item`, where `$index` is the index of the request item that failed the condition check. This value defaults to true.

# Projections
<a name="aws-appsync-resolver-mapping-template-reference-dynamodb-projections"></a>

When reading objects in DynamoDB using the `GetItem`, `Scan`, `Query`, `BatchGetItem`, and `TransactGetItems` operations, you can optionally specify a projection that identifies the attributes that you want. The projection has the following structure, which is similar to filters: 

```
"projection" : {
    "expression" : "projection expression"
    "expressionNames" : {
        "#name" : "name",
    }
}
```

The fields are defined as follows:

**`expression`**   
The projection expression, which is a string. To retrieve a single attribute, specify its name. For multiple attributes, the names must be comma-separated values. For more information on writing projection expressions, see the [DynamoDB projection expressions](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html) documentation. This field is required. 

 **`expressionNames`**   
The substitutions for expression attribute *name* placeholders in the form of key-value pairs. The key corresponds to a name placeholder used in the `expression`. The value must be a string that corresponds to the attribute name of the item in DynamoDB. This field is optional and should only be populated with substitutions for expression attribute name placeholders used in the `expression`. For more information about `expressionNames`, see the [DynamoDB documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html). 

## Example 1
<a name="id25"></a>

The following example is a projection section for a VTL mapping template in which only the attributes `author` and `id` are returned from DynamoDB:

```
"projection" : {
    "expression" : "#author, id",
    "expressionNames" : {
        "#author" : "author"
    }
}
```

**Tip**  
You can access your GraphQL request selection set using [\$1context.info.selectionSetList](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html#aws-appsync-resolver-context-reference-info). This field allows you to frame your projection expression dynamically according to your requirements.

**Note**  
While using projection expressions with the `Query` and `Scan` operations, the value for `select` must be `SPECIFIC_ATTRIBUTES`. For more information, see the [DynamoDB documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html#DDB-Query-request-Select).

# AWS AppSync resolver mapping template reference for RDS
<a name="resolver-mapping-template-reference-rds"></a>

The AWS AppSync RDS resolver mapping templates allow developers to send SQL queries to a Data API for Amazon Aurora Serverless and get back the result of these queries.

## Request mapping template
<a name="request-mapping-template"></a>

The RDS request mapping template is fairly simple:

```
{
    "version": "2018-05-29",
    "statements": [],
    "variableMap": {},
    "variableTypeHintMap": {}
}
```

Here is the JSON schema representation of the RDS request mapping template, once resolved.

```
{
    "definitions": {},
    "$schema": "https://json-schema.org/draft-07/schema#",
    "$id": "https://example.com/root.json",
    "type": "object",
    "title": "The Root Schema",
    "required": [
        "version",
        "statements",
        "variableMap"
    ],
    "properties": {
        "version": {
            "$id": "#/properties/version",
            "type": "string",
            "title": "The Version Schema",
            "default": "",
            "examples": [
                "2018-05-29"
            ],
            "enum": [
                "2018-05-29"
            ],
            "pattern": "^(.*)$"
        },
        "statements": {
            "$id": "#/properties/statements",
            "type": "array",
            "title": "The Statements Schema",
            "items": {
                "$id": "#/properties/statements/items",
                "type": "string",
                "title": "The Items Schema",
                "default": "",
                "examples": [
                    "SELECT * from BOOKS"
                ],
                "pattern": "^(.*)$"
            }
        },
        "variableMap": {
            "$id": "#/properties/variableMap",
            "type": "object",
            "title": "The Variablemap Schema"
        },
        "variableTypeHintMap": {
            "$id": "#/properties/variableTypeHintMap",
            "type": "object",
            "title": "The variableTypeHintMap Schema"
        }
    }
}
```

The following is an example of the request mapping template with a static query:

```
{
    "version": "2018-05-29",
    "statements": [
        "select title, isbn13 from BOOKS where author = 'Mark Twain'"
    ]
}
```

## Version
<a name="version"></a>

Common to all request mapping templates, the version field defines the version that the template uses. The version field is required. The value “2018-05-29” is the only version supported for the Amazon RDS mapping templates.

```
"version": "2018-05-29"
```

## Statements and VariableMap
<a name="statements-variablemap"></a>

The statements array is a placeholder for the developer-provided queries. Currently, up to two queries per request mapping template are supported. The `variableMap` is an optional field that contains aliases that can be used to make the SQL statements shorter and more readable. For example, the following is possible:

```
{
"version": "2018-05-29",
    "statements": [
        "insert into BOOKS VALUES (:AUTHOR, :TITLE, :ISBN13)",
        "select * from BOOKS WHERE isbn13 = :ISBN13"
    ],
    "variableMap": {
        ":AUTHOR": $util.toJson($ctx.args.newBook.author),
        ":TITLE": $util.toJson($ctx.args.newBook.title),
        ":ISBN13": $util.toJson($ctx.args.newBook.isbn13)
    }
}
```

AWS AppSync will use the variable map values to construct the **[SqlParameterized](https://docs.aws.amazon.com/rdsdataservice/latest/APIReference/API_SqlParameter.html)** queries that will be sent to the Amazon Aurora Serverless Data API. The SQL statements are executed with parameters provided in the variable map, which eliminates the risk of SQL injection. 

## VariableTypeHintMap
<a name="variabletypehintmap"></a>

The `variableTypeHintMap` is an optional field containing aliased types that can be used to send [SQL parameter](https://docs.aws.amazon.com/rdsdataservice/latest/APIReference/API_SqlParameter.html) type hints. These type hints avoid explicit casting in the SQL statements, making them shorter. For example, the following is possible:

```
{
    "version": "2018-05-29",
    "statements": [
        "insert into LOGINDATA VALUES (:ID, :TIME)",
        "select * from LOGINDATA WHERE id = :ID"
     ],
     "variableMap": {
        ":ID": $util.toJson($ctx.args.id),
        ":TIME": $util.toJson($ctx.args.time)
     },
     "variableTypeHintMap": {
        ":id": "UUID",
        ":time": "TIME"
     }
}
```

AWS AppSync will use the variable map value to construct the queries that are sent to the Amazon Aurora Serverless Data API. It also uses the `variableTypeHintMap` data and sends the type's information to RDS. RDS-supported `typeHints` can be found [here](https://docs.aws.amazon.com/rdsdataservice/latest/APIReference/API_SqlParameter.html).

# AWS AppSync resolver mapping template reference for OpenSearch
<a name="resolver-mapping-template-reference-elasticsearch"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The AWS AppSync resolver for Amazon OpenSearch Service enables you to use GraphQL to store and retrieve data in existing OpenSearch Service domains in your account. This resolver works by allowing you to map an incoming GraphQL request into an OpenSearch Service request, then map the OpenSearch Service response back to GraphQL. This section describes the mapping templates for the supported OpenSearch Service operations.

## Request mapping template
<a name="request-mapping-template"></a>

Most OpenSearch Service request mapping templates have a common structure where just a few pieces change. The following example runs a search against an OpenSearch Service domain, where documents are organized under an index called `post`. The search parameters are defined in the `body` section, with many of the common query clauses being defined in the `query` field. This example will search for documents containing `"Nadia"`, or `"Bailey"`, or both, in the `author` field of a document:

```
{
    "version":"2017-02-28",
    "operation":"GET",
    "path":"/post/_search",
    "params":{
        "headers":{},
        "queryString":{},
        "body":{
            "from":0,
            "size":50,
            "query" : {
                "bool" : {
                    "should" : [
                        {"match" : { "author" : "Nadia" }},
                        {"match" : { "author" : "Bailey" }}
                    ]
                }
            }
        }
    }
}
```

## Response mapping template
<a name="response-mapping-template"></a>

As with other data sources, OpenSearch Service sends a response to AWS AppSync that needs to be converted to GraphQL. .

Most GraphQL queries are looking for the `_source` field from an OpenSearch Service response. Because you can do searches to return either an individual document or a list of documents, there are two common response mapping templates used in OpenSearch Service:

 **List of Results** 

```
[
    #foreach($entry in $context.result.hits.hits)
      #if( $velocityCount > 1 ) , #end
        $utils.toJson($entry.get("_source"))
    #end
]
```

 **Individual Item** 

```
$utils.toJson($context.result.get("_source"))
```

## `operation` field
<a name="operation-field"></a>

**Note**  
This applies only to the Request mapping template. 

HTTP method or verb (GET, POST, PUT, HEAD or DELETE) that AWS AppSync sends to the OpenSearch Service domain. Both the key and the value must be a string.

```
"operation" : "PUT"
```

## `path` field
<a name="path-field"></a>

**Note**  
This applies only to the Request mapping template. 

The search path for an OpenSearch Service request from AWS AppSync. This forms a URL for the operation’s HTTP verb. Both the key and the value must be strings.

```
"path" : "/<indexname>/_doc/<_id>"
"path" : "/<indexname>/_doc"
"path" : "/<indexname>/_search"
"path" : "/<indexname>/_update/<_id>
```

When the mapping template is evaluated, this path is sent as part of the HTTP request, including the OpenSearch Service domain. For example, the previous example might translate to:

```
GET https://opensearch-domain-name.REGION.es.amazonaws.com/indexname/type/_search
```

## `params` field
<a name="params-field"></a>

**Note**  
This applies only to the Request mapping template. 

Used to specify what action your search performs, most commonly by setting the **query** value inside of the **body**. However, there are several other capabilities that can be configured, such as the formatting of responses.
+  **headers** 

  The header information, as key-value pairs. Both the key and the value must be strings. For example:

  ```
  "headers" : {
      "Content-Type" : "application/json"
  }
  ```
**Note**  
AWS AppSync currently supports only JSON as a `Content-Type`.
+  **queryString** 

  Key-value pairs that specify common options, such as code formatting for JSON responses. Both the key and the value must be a string. For example, if you want to get pretty-formatted JSON, you would use:

  ```
  "queryString" : {
      "pretty" : "true"
  }
  ```
+  **body** 

  This is the main part of your request, allowing AWS AppSync to craft a well-formed search request to your OpenSearch Service domain. The key must be a string comprised of an object. A couple of demonstrations are shown below.

 **Example 1** 

Return all documents with a city matching “seattle”:

```
"body":{
    "from":0,
    "size":50,
    "query" : {
        "match" : {
            "city" : "seattle"
        }
    }
}
```

 **Example 2** 

Return all documents matching “washington” as the city or the state:

```
"body":{
    "from":0,
    "size":50,
    "query" : {
        "multi_match" : {
            "query" : "washington",
            "fields" : ["city", "state"]
        }
    }
}
```

## Passing variables
<a name="passing-variables"></a>

**Note**  
This applies only to the Request mapping template. 

You can also pass variables as part of evaluation in the VTL statement. For example, suppose you had a GraphQL query such as the following:

```
query {
    searchForState(state: "washington"){
        ...
    }
}
```

The mapping template could take the state as an argument:

```
"body":{
    "from":0,
    "size":50,
    "query" : {
        "multi_match" : {
            "query" : "$context.arguments.state",
            "fields" : ["city", "state"]
        }
    }
}
```

For a list of utilities you can include in the VTL, see [Access Request Headers](resolver-context-reference.md#aws-appsync-resolver-context-reference-util).

# AWS AppSync resolver mapping template reference for Lambda
<a name="resolver-mapping-template-reference-lambda"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

You can use AWS AppSync functions and resolvers to invoke Lambda functions located in your account. You can shape your request payloads and the response from your Lambda functions before returning them to your clients. You can also use mapping templates to give hints to AWS AppSync about the nature of the operation to be invoked. This section describes the different mapping templates for the supported Lambda operations.

## Request mapping template
<a name="request-mapping-template"></a>

The Lambda request mapping template handles fields related to your Lambda function:

```
{
  "version": string,
  "operation": Invoke|BatchInvoke,
  "payload": any type,
  "invocationType": RequestResponse|Event
}
```

This is the JSON schema representation of the Lambda request mapping template when resolved:

```
{
  "definitions": {},
  "$schema": "https://json-schema.org/draft-06/schema#",
  "$id": "https://aws.amazon.com/appsync/request-mapping-template.json",
  "type": "object",
  "properties": {
    "version": {
      "$id": "/properties/version",
      "type": "string",
      "enum": [
        "2018-05-29"
      ],
      "title": "The Mapping template version.",
      "default": "2018-05-29"
    },
    "operation": {
      "$id": "/properties/operation",
      "type": "string",
      "enum": [
        "Invoke",
        "BatchInvoke"
      ],
      "title": "The Mapping template operation.",
      "description": "What operation to execute.",
      "default": "Invoke"
    },
    "payload": {},
    "invocationType": {
      "$id": "/properties/invocationType",
      "type": "string",
      "enum": [
        "RequestResponse",
        "Event"
      ],
      "title": "The Mapping template invocation type.",
      "description": "What invocation type to execute.",
      "default": "RequestResponse"
    }
  },
  "required": [
    "version",
    "operation"
  ],
  "additionalProperties": false
}
```

Here's an example that uses an `invoke` operation with its payload data being the `getPost` field from a GraphQL schema along with its arguments from the context:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "payload": {
    "field": "getPost",
    "arguments": $util.toJson($context.arguments)
  }
}
```

The entire mapping document is passed as the input to your Lambda function so that the previous example now looks like this:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "payload": {
    "field": "getPost",
    "arguments": {
      "id": "postId1"
    }
  }
}
```

### Version
<a name="version"></a>

Common to all request mapping templates, the `version` defines the version that the template uses. The `version` is required and is a static value:

```
"version": "2018-05-29"
```

### Operation
<a name="operation"></a>

The Lambda data source lets you define two operations in the `operation` field: `Invoke` and `BatchInvoke`. The `Invoke` operation lets AWS AppSync know to call your Lambda function for every GraphQL field resolver. `BatchInvoke` instructs AWS AppSync to batch requests for the current GraphQL field. The `operation` field is required.

For `Invoke`, the resolved request mapping template matches the input payload of the Lambda function. Let's modify the example above:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
    "payload": {
      "arguments": $util.toJson($context.arguments)
    }
}
```

This is resolved and passed to the Lambda function, which could look something like this:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
    "payload": {
      "arguments": {
        "id": "postId1"
      }
    }
}
```

For `BatchInvoke`, the mapping template is applied to every field resolver in the batch. For conciseness, AWS AppSync merges all the resolved mapping template `payload` values into a list under a single object matching the mapping template. The following example template shows the merge:

```
{
  "version": "2018-05-29",
  "operation": "BatchInvoke",
  "payload": $util.toJson($context)
}
```

This template is resolved into the following mapping document:

```
{
  "version": "2018-05-29",
  "operation": "BatchInvoke",
  "payload": [
    {...}, // context for batch item 1
    {...}, // context for batch item 2
    {...}  // context for batch item 3
  ]
}
```

Each element of the `payload` list corresponds to a single batch item. The Lambda function is also expected to return a list-shaped response matching the order of the items sent in the request:

```
[
  { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 1
  { "data": {...}, "errorMessage": null, "errorType": null }, // result for batch item 2
  { "data": {...}, "errorMessage": null, "errorType": null }  // result for batch item 3
]
```

### Payload
<a name="payload"></a>

The `payload` field is a container used to pass any well-formed JSON to the Lambda function. If the `operation` field is set to `BatchInvoke`, AWS AppSync wraps the existing `payload` values into a list. The `payload` field is optional.

### Invocation type
<a name="async-invocation-type"></a>

The Lambda data source allows you to define two invocation types: `RequestResponse` and `Event`. The invocation types are synonymous with the invocation types defined in the [Lambda API](https://docs.aws.amazon.com//lambda/latest/api/API_Invoke.html). The `RequestResponse` invocation type lets AWS AppSync call your Lambda function synchronously to wait for a response. The `Event` invocation allows you to invoke your Lambda function asynchronously. For more information on how Lambda handles `Event` invocation type requests, see [Asynchronous invocation](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html). The `invocationType` field is optional. If this field is not included in the request, AWS AppSync will default to the `RequestResponse` invocation type.

For any `invocationType` field, the resolved request matches the input payload of the Lambda function. Let's modify the example above:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "invocationType": "Event"
  "payload": {
    "arguments": $util.toJson($context.arguments)
  }
}
```

This is resolved and passed to the Lambda function, which could look something like this:

```
{
  "version": "2018-05-29",
  "operation": "Invoke",
  "invocationType": "Event",
  "payload": {
    "arguments": {
      "id": "postId1"
    }
  }
}
```

When the `BatchInvoke` operation is used in conjunction with the `Event` invocation type field, AWS AppSync merges the field resolver in the same way mentioned above, and the request is passed to your Lambda function as an asynchronous event with the `payload` being a list of values. We recommend that you disable resolver caching for `Event` invocation type resolvers because these would not be sent to Lambda if there were a cache hit.

## Response mapping template
<a name="response-mapping-template"></a>

As with other data sources, your Lambda function sends a response to AWS AppSync that must be converted to a GraphQL type.

The result of the Lambda function is set on the `context` object that is available via the Velocity Template Language (VTL) `$context.result` property.

If the shape of your Lambda function response exactly matches the shape of the GraphQL type, you can forward the response using the following response mapping template:

```
$util.toJson($context.result)
```

There are no required fields or shape restrictions that apply to the response mapping template. However, because GraphQL is strongly typed, the resolved mapping template must match the expected GraphQL type.

## Lambda function batched response
<a name="aws-appsync-resolver-mapping-template-reference-lambda-batched-response"></a>

If the `operation` field is set to `BatchInvoke`, AWS AppSync expects a list of items back from the Lambda function. In order for AWS AppSync to map each result back to the original request item, the response list must match in size and order. It's valid to have `null` items in the response list; `$ctx.result` is set to *null* accordingly.

## Direct Lambda Resolvers
<a name="direct-lambda-resolvers"></a>

If you wish to circumvent the use of mapping templates entirely, AWS AppSync can provide a default payload to your Lambda function and a default Lambda function response to a GraphQL type. You can choose to provide a request template, a response template, or neither, and AWS AppSync handles it accordingly.

### Direct Lambda request mapping template
<a name="lambda-mapping-template-bypass-request"></a>

When the request mapping template is not provided, AWS AppSync will send the `Context` object directly to your Lambda function as an `Invoke` operation. For more information about the structure of the `Context` object, see [AWS AppSync resolver mapping template context reference](resolver-context-reference.md).

### Direct Lambda response mapping template
<a name="lambda-mapping-template-bypass-response"></a>

When the response mapping template is not provided, AWS AppSync does one of two things upon receiving your Lambda function's response. If you did not provide a request mapping template or if you provided a request mapping template with the version `2018-05-29`, the response will be equivalent to the following response mapping template:

```
#if($ctx.error)
     $util.error($ctx.error.message, $ctx.error.type, $ctx.result)
 #end
 $util.toJson($ctx.result)
```

If you provided a template with the version `2017-02-28`, the response logic functions equivalently to the following response mapping template:

```
$util.toJson($ctx.result)
```

Superficially, the mapping template bypass operates similarly to using certain mapping templates as shown in the preceding examples. However, behind the scenes, the evaluation of the mapping templates is circumvented entirely. Because the template evaluation step is bypassed, applications might experience less overhead and latency during the response in some scenarios compared to a Lambda function with a response mapping template that needs to be evaluated. 

### Custom error handling in Direct Lambda Resolver responses
<a name="lambda-mapping-template-bypass-errors"></a>

You can customize error responses from Lambda functions that Direct Lambda Resolvers invoke by raising a custom exception. The following example demonstrates how to create a custom exception using JavaScript:

```
class CustomException extends Error {
  constructor(message) {
    super(message);
    this.name = "CustomException";
  }
}
 
throw new CustomException("Custom message");
```

When exceptions are raised, the `errorType` and `errorMessage` are the `name` and `message`, respectively, of the custom error that is thrown.

If `errorType` is `UnauthorizedException`, AWS AppSync returns the default message (`"You are not authorized to make this call."`) instead of a custom message.

The following snippet is an example GraphQL response that demonstrates a custom `errorType`:

```
{
  "data": {
    "query": null
  },
  "errors": [
    {
      "path": [
        "query"
      ],
      "data": null,
      "errorType": "CustomException",
      "errorInfo": null,
      "locations": [
        {
          "line": 5,
          "column": 10,
          "sourceName": null
        }
      ],
      "message": "Custom Message"
    }
  ]
}
```

### Direct Lambda Resolvers: Batching enabled
<a name="lambda-resolvers-batching"></a>

You can enable batching for your Direct Lambda Resolver by configuring the `maxBatchSize` on your resolver. When `maxBatchSize` is set to a value greater than `0` for a Direct Lambda resolver, AWS AppSync sends requests in batches to your Lambda function in sizes up to `maxBatchSize`. 

Setting `maxBatchSize` to `0` on a Direct Lambda resolver turns off batching.

For more information on how batching with Lambda resolvers works, see [Advanced use case: Batching](tutorial-lambda-resolvers.md#advanced-use-case-batching).

#### Request mapping template
<a name="lambda-resolvers-batching-request-template"></a>

When batching is enabled and the request mapping template is not provided, AWS AppSync sends a list of `Context` objects as a `BatchInvoke` operation directly to your Lambda function.

#### Response mapping template
<a name="lambda-resolvers-batching-response-template"></a>

When batching is enabled and the response mapping template is not provided, the response logic is equivalent to the following response mapping template:

```
#if( $context.result && $context.result.errorMessage )
      $utils.error($context.result.errorMessage, $context.result.errorType,
      $context.result.data)
#else
      $utils.toJson($context.result.data)
#end
```

The Lambda function must return a list of results in the same order as the list of `Context` objects that were sent. You can return individual errors by providing an `errorMessage` and `errorType` for a specific result. Each result in the list has the following format:

```
{
   "data" : { ... }, // your data
   "errorMessage" : { ... }, // optional, if included an error entry is added to the "errors" object in the AppSync response 
   "errorType" : { ... } // optional, the error type
}
```

**Note**  
Other fields in the result object are currently ignored.

#### Handling errors from Lambda
<a name="lambda-resolvers-batching-error-handling"></a>

You can return an error for all results by throwing an exception or an error in your Lambda function. If the payload request or response size for your batch request is too large, Lambda returns an error. In that case, you should consider reducing your `maxBatchSize` or reducing the size of the response payload.

For information on handling individual errors, see [Returning individual errors](tutorial-lambda-resolvers.md#returning-individual-errors).

#### Sample Lambda functions
<a name="sample-lambda-function"></a>

Using the schema below, you can create a Direct Lambda Resolver for the `Post.relatedPosts` field resolver and enable batching by setting `maxBatchSize` above `0`:

```
schema {
    query: Query
    mutation: Mutation
}

type Query {
    getPost(id:ID!): Post
    allPosts: [Post]
}

type Mutation {
    addPost(id: ID!, author: String!, title: String, content: String, url: String): Post!
}

type Post {
    id: ID!
    author: String!
    title: String
    content: String
    url: String
    ups: Int
    downs: Int
    relatedPosts: [Post]
}
```

In the following query, the Lambda function will be called with batches of requests to resolve `relatedPosts`:

```
query getAllPosts {
  allPosts {
    id
    relatedPosts {
      id
    }
  }
}
```

A simple implementation of a Lambda function is provided below:

```
const posts = {
  1: {
    id: '1',
    title: 'First book',
    author: 'Author1',
    url: 'https://amazon.com/',
    content:
      'SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1 SAMPLE TEXT AUTHOR 1',
    ups: '100',
    downs: '10',
  },
  2: {
    id: '2',
    title: 'Second book',
    author: 'Author2',
    url: 'https://amazon.com',
    content: 'SAMPLE TEXT AUTHOR 2 SAMPLE TEXT AUTHOR 2 SAMPLE TEXT',
    ups: '100',
    downs: '10',
  },
  3: { id: '3', title: 'Third book', author: 'Author3', url: null, content: null, ups: null, downs: null },
  4: {
    id: '4',
    title: 'Fourth book',
    author: 'Author4',
    url: 'https://www.amazon.com/',
    content:
      'SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4 SAMPLE TEXT AUTHOR 4',
    ups: '1000',
    downs: '0',
  },
  5: {
    id: '5',
    title: 'Fifth book',
    author: 'Author5',
    url: 'https://www.amazon.com/',
    content: 'SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT AUTHOR 5 SAMPLE TEXT',
    ups: '50',
    downs: '0',
  },
}

const relatedPosts = {
  1: [posts['4']],
  2: [posts['3'], posts['5']],
  3: [posts['2'], posts['1']],
  4: [posts['2'], posts['1']],
  5: [],
}
exports.handler = async (event) => {
  console.log('event ->', event)
  // retrieve the ID of each post
  const ids = event.map((context) => context.source.id)
  // fetch the related posts for each post id
  const related = ids.map((id) => relatedPosts[id])

  // return the related posts; or an error if none were found
  return related.map((r) => {
    if (r.length > 0) {
      return { data: r }
    } else {
      return { data: null, errorMessage: 'Not found', errorType: 'ERROR' }
    }
  })
}
```

# AWS AppSync resolver mapping template reference for EventBridge
<a name="resolver-mapping-template-reference-eventbridge"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The AWS AppSync resolver mapping template used with the EventBridge data source allows you to send custom events to the Amazon EventBridge bus.

## Request mapping template
<a name="request-mapping-template"></a>

The `PutEvents` request mapping template allows you to send multiple custom events to an EventBridge event bus. The mapping document has the following structure:

```
{
    "version" : "2018-05-29", 
    "operation" : "PutEvents",
    "events" : [{}]
}
```

The following is an example of a request mapping template for EventBridge: 

```
{
    "version": "2018-05-29",
    "operation": "PutEvents",
    "events": [{
        "source": "com.mycompany.myapp",
        "detail": {
            "key1" : "value1",
            "key2" : "value2"
        },
        "detailType": "myDetailType1"
    },
    {
        "source": "com.mycompany.myapp",
        "detail": {
            "key3" : "value3",
            "key4" : "value4"
        },
        "detailType": "myDetailType2",
        "resources" : ["Resource1", "Resource2"],
        "time" : "2023-01-01T00:30:00.000Z"
    }
    
    ]
}
```

## Response mapping template
<a name="response-mapping-template"></a>

If the `PutEvents` operation is successful, the response from EventBridge is included in the `$ctx.result`:

```
#if($ctx.error)
  $util.error($ctx.error.message, $ctx.error.type, $ctx.result)
#end
  $util.toJson($ctx.result)
```

Errors that occur while performing `PutEvents` operations such as `InternalExceptions` or `Timeouts` will appear in `$ctx.error`. For a list of EventBridge's common errors, see the [EventBridge common error reference](https://docs.aws.amazon.com/eventbridge/latest/APIReference/CommonErrors.html).

The `result` will be in the following format:

```
{
    "Entries" [
        {
            "ErrorCode" : String,
            "ErrorMessage" : String,
            "EventId" : String
        }
    ],
    "FailedEntryCount" : number
}
```
+ **Entries**

  The ingested event results, both successful and unsuccessful. If the ingestion was successful, the entry has the `EventID` in it. Otherwise, you can use the `ErrorCode` and `ErrorMessage` to identify the problem with the entry.

  For each record, the index of the response element is the same as the index in the request array.
+ **FailedEntryCount**

  The number of failed entries. This value is represented as an integer.

For more information about the response of `PutEvents`, see [PutEvents](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html#API_PutEvents_ResponseElements).

**Example sample response 1**

The following example is a `PutEvents` operation with two successful events:

```
{
    "Entries" : [ 
        {
            "EventId": "11710aed-b79e-4468-a20b-bb3c0c3b4860"
        }, 
        {
            "EventId": "d804d26a-88db-4b66-9eaf-9a11c708ae82"
        }
    ],
    "FailedEntryCount" : 0
}
```

**Example sample response 2**

The following example is a `PutEvents` operation with three events, two successes and one fail:

```
{
    "Entries" : [ 
        {
            "EventId": "11710aed-b79e-4468-a20b-bb3c0c3b4860"
        }, 
        {
            "EventId": "d804d26a-88db-4b66-9eaf-9a11c708ae82"
        },
        {
            "ErrorCode" : "SampleErrorCode",
            "ErrorMessage" : "Sample Error Message"
        }
    ],
    "FailedEntryCount" : 1
}
```

## `PutEvents` fields
<a name="putevents-field"></a>

`PutEvents` contains the following mapping template fields:
+ **Version**

  Common to all request mapping templates, the `version` field defines the version that the template uses. This field is required. The value `2018-05-29` is the only version supported for the EventBridge mapping templates.
+ **Operation**

  The only supported operation is `PutEvents`. This operation allows you to add custom events to your event bus.
+ **Events**

  An array of events that will be added to the event bus. This array should have an allocation of 1 - 10 items.

  The `Event` object is a valid JSON object that has the following fields:
  + `"source"`: A string that defines the source of the event.
  + `"detail"`: A JSON object that you can use to attach information about the event. This field can be an empty map ( `{ }` ).
  + `"detailType`: A string that identifies the type of event.
  + `"resources"`: A JSON array of strings that identifies resources involved in the event. This field can be an empty array.
  + `"time"`: The event timestamp provided as a string. This should follow the [RFC3339](https://www.rfc-editor.org/rfc/rfc3339.txt) timestamp format.

The snippets below are some examples of valid `Event` objects:

**Example 1**

```
{
    "source" : "source1",
    "detail" : {
        "key1" : [1,2,3,4],
        "key2" : "strval"
    },
    "detailType" : "sampleDetailType",
    "resources" : ["Resouce1", "Resource2"],
    "time" : "2022-01-10T05:00:10Z"
}
```

**Example 2**

```
{
    "source" : "source1",
    "detail" : {},
    "detailType" : "sampleDetailType"
}
```

**Example 3**

```
{
    "source" : "source1",
    "detail" : {
        "key1" : 1200
    },
    "detailType" : "sampleDetailType",
    "resources" : []
}
```

# AWS AppSync resolver mapping template reference for `None` data source
<a name="resolver-mapping-template-reference-none"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The AWS AppSync resolver mapping template used with the data source of type *None*, enables you to shape requests for AWS AppSync local operations.

## Request mapping template
<a name="request-mapping-template"></a>

The mapping template is simple and enables you to pass as much context information as possible via the `payload` field.

```
{
   "version": string,
   "payload": any type
}
```

Here is the JSON schema representation of the request mapping template, once resolved:

```
{
    "definitions": {},
    "$schema": "https://json-schema.org/draft-06/schema#",
    "$id": "https://aws.amazon.com/appsync/request-mapping-template.json",
    "type": "object",
    "properties": {
        "version": {
            "$id": "/properties/version",
            "type": "string",
            "enum": [
                "2018-05-29"
            ],
            "title": "The Mapping template version.",
            "default": "2018-05-29"
        },
        "payload": {}
    },
    "required": [
        "version"
    ],
    "additionalProperties": false
}
```

Here is an example where the field arguments are passed via the VTL context property `$context.arguments`:

```
{
    "version": "2018-05-29",
    "payload": $util.toJson($context.arguments)
}
```

The value of the `payload` field will be forwarded to the response mapping template and available on the VTL context property (`$context.result`).

This is an example representing the interpolated value of the `payload` field:

```
{
    "id": "postId1"
}
```

## Version
<a name="version"></a>

Common to all request mapping templates, the `version` field defines the version used by the template.

 The `version` field is required.

Example:

```
"version": "2018-05-29"
```

## Payload
<a name="payload"></a>

The `payload` field is a container that can be used to pass any well-formed JSON to the response mapping template.

 The `payload` field is optional.

## Response mapping template
<a name="response-mapping-template"></a>

Because there is no data source, the value of the `payload` field will be forwarded to the response mapping template and set on the `context` object that is available via the VTL `$context.result` property.

If the shape of the `payload` field value exactly matches the shape of the GraphQL type, you can forward the response using the following response mapping template:

```
$util.toJson($context.result)
```

There are no required fields or shape restrictions that apply to the response mapping template. However, because GraphQL is strongly typed, the resolved mapping template must match the expected GraphQL type.

# AWS AppSync resolver mapping template reference for HTTP
<a name="resolver-mapping-template-reference-http"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

The AWS AppSync HTTP resolver mapping templates enable you to send requests from AWS AppSync to any HTTP endpoint, and responses from your HTTP endpoint back to AWS AppSync. By using mapping templates, you can provide hints to AWS AppSync about the nature of the operation to be invoked. This section describes the different mapping templates for the supported HTTP resolver.

## Request mapping template
<a name="request-mapping-template"></a>

```
{
    "version": "2018-05-29",
    "method": "PUT|POST|GET|DELETE|PATCH",
    "params": {
        "query": Map,
        "headers": Map,
        "body": any
    },
    "resourcePath": string
}
```

After the HTTP request mapping template is resolved, the JSON schema representation of the request mapping template looks like the following:

```
{
    "$id": "https://aws.amazon.com/appsync/request-mapping-template.json",
    "type": "object",
    "properties": {
        "version": {
        "$id": "/properties/version",
        "type": "string",
        "title": "The Version Schema ",
        "default": "",
        "examples": [
            "2018-05-29"
        ],
        "enum": [
            "2018-05-29"
        ]
        },
        "method": {
        "$id": "/properties/method",
        "type": "string",
        "title": "The Method Schema ",
        "default": "",
        "examples": [
            "PUT|POST|GET|DELETE|PATCH"
        ],
        "enum": [
            "PUT",
            "PATCH",
            "POST",
            "DELETE",
            "GET"
        ]
        },
        "params": {
        "$id": "/properties/params",
        "type": "object",
        "properties": {
            "query": {
            "$id": "/properties/params/properties/query",
            "type": "object"
            },
            "headers": {
            "$id": "/properties/params/properties/headers",
            "type": "object"
            },
            "body": {
            "$id": "/properties/params/properties/body",
            "type": "string",
            "title": "The Body Schema ",
            "default": "",
            "examples": [
                ""
            ]
            }
        }
        },
        "resourcePath": {
        "$id": "/properties/resourcePath",
        "type": "string",
        "title": "The Resourcepath Schema ",
        "default": "",
        "examples": [
            ""
        ]
        }
    },
    "required": [
        "version",
        "method",
        "resourcePath"
    ]
}
```

Following is an example of an HTTP POST request, with a `text/plain` body:

```
{
    "version": "2018-05-29",
    "method": "POST",
    "params": {
        "headers":{
        "Content-Type":"text/plain"
        },
        "body":"this is an example of text body"
    },
    "resourcePath": "/"
}
```

## Version
<a name="version"></a>

**Note**  
This applies only to the Request mapping template. 

Defines the version that the template uses. `version` is common to all request mapping templates and is required.

```
"version": "2018-05-29"
```

## Method
<a name="method"></a>

**Note**  
This applies only to the Request mapping template. 

HTTP method or verb (GET, POST, PUT, PATCH, or DELETE) that AWS AppSync sends to the HTTP endpoint.

```
"method": "PUT"
```

## ResourcePath
<a name="resourcepath"></a>

**Note**  
This applies only to the Request mapping template. 

The resource path that you want to access. Along with the endpoint in the HTTP data source, the resource path forms the URL that the AWS AppSync service makes a request to.

```
"resourcePath": "/v1/users"
```

When the mapping template is evaluated, this path is sent as part of the HTTP request, including the HTTP endpoint. For example, the previous example might translate to the following:

```
PUT <endpoint>/v1/users
```

## Params fields
<a name="params-field"></a>

**Note**  
This applies only to the Request mapping template. 

Used to specify what action your search performs, most commonly by setting the **query** value inside the **body**. However, there are several other capabilities that can be configured, such as the formatting of responses.

** **headers** **  
The header information, as key-value pairs. Both the key and the value must be strings.  
For example:  

```
"headers" : {
    "Content-Type" : "application/json"
}
```
Currently supported `Content-Type` headers are:  

```
text/*
application/xml
application/json
application/soap+xml
application/x-amz-json-1.0
application/x-amz-json-1.1
application/vnd.api+json
application/x-ndjson
```
 **Note**: You can’t set the following HTTP headers:  

```
HOST
CONNECTION
USER-AGENT
EXPECTATION
TRANSFER_ENCODING
CONTENT_LENGTH
```

** **query** **  
Key-value pairs that specify common options, such as code formatting for JSON responses. Both the key and the value must be a string. The following example shows how you can send a query string as `?type=json`:  

```
"query" : {
    "type" : "json"
}
```

** **body** **  
The body contains the HTTP request body that you choose to set. The request body is always a UTF-8 encoded string unless the content type specifies the charset.  

```
"body":"body string"
```

## Response
<a name="response"></a>

See an example [here](https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-http-resolvers.html).

# Certificate Authorities (CA) Recognized by AWS AppSync for HTTPS Endpoints
<a name="http-cert-authorities"></a>

**Note**  
Let's Encrypt is accepted via the *identrust* and *isrgrootx1* certificates. No action on your part is required if you use Let's Encrypt.

At this time, self-signed certificates are not supported by HTTP resolvers when using HTTPS. AWS AppSync recognizes the following Certificate Authorities when resolving SSL/TLS certificates for HTTPS:


**Known root certificates in AWS AppSync**  

| Name | Date | SHA1 Fingerprint | 
| --- | --- | --- | 
| digicertassuredidrootca |  Apr 21, 2018 | 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43 | 
| trustcenterclass2caii |  Apr 21, 2018 | AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E | 
| thawtepremiumserverca |  Apr 21, 2018 | E0:AB:05:94:20:72:54:93:05:60:62:02:36:70:F7:CD:2E:FC:66:66 | 
| cia-crt-g3-02-ca |  Nov 23, 2016 | 96:4A:BB:A7:BD:DA:FC:97:34:C0:0A:2D:F0:05:98:F7:E6:C6:6F:09 | 
| swisssignplatinumg2ca |  Apr 21, 2018 | 56:E0:FA:C0:3B:8F:18:23:55:18:E5:D3:11:CA:E8:C2:43:31:AB:66 | 
| swisssignsilverg2ca |  Apr 21, 2018 | 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB | 
| thawteserverca |  Apr 21, 2018 | 9F:AD:91:A6:CE:6A:C6:C5:00:47:C4:4E:C9:D4:A5:0D:92:D8:49:79 | 
| equifaxsecureebusinessca1 |  Apr 21, 2018 | AE:E6:3D:70:E3:76:FB:C7:3A:EB:B0:A1:C1:D4:C4:7A:A7:40:B3:F4 | 
| securetrustca |  Apr 21, 2018 | 87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11 | 
| utnuserfirstclientauthemailca |  Apr 21, 2018 | B1:72:B1:A5:6D:95:F9:1F:E5:02:87:E1:4D:37:EA:6A:44:63:76:8A | 
| thawtepersonalfreemailca |  Apr 21, 2018 | E6:18:83:AE:84:CA:C1:C1:CD:52:AD:E8:E9:25:2B:45:A6:4F:B7:E2 | 
| affirmtrustnetworkingca |  Apr 21, 2018 | 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F | 
| entrustevca |  Apr 21, 2018 | B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 | 
| utnuserfirsthardwareca |  Apr 21, 2018 | 04:83:ED:33:99:AC:36:08:05:87:22:ED:BC:5E:46:00:E3:BE:F9:D7 | 
| certumca |  Apr 21, 2018 | 62:52:DC:40:F7:11:43:A2:2F:DE:9E:F7:34:8E:06:42:51:B1:81:18 | 
| addtrustclass1ca |  Apr 21, 2018 | CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D | 
| entrustrootcag2 |  Apr 21, 2018 | 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4 | 
| equifaxsecureca |  Apr 21, 2018 | D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A | 
| quovadisrootca3 |  Apr 21, 2018 | 1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85 | 
| quovadisrootca2 |  Apr 21, 2018 | CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7 | 
| digicertglobalrootg2 |  Apr 21, 2018 | DF:3C:24:F9:BF:D6:66:76:1B:26:80:73:FE:06:D1:CC:8D:4F:82:A4 | 
| digicerthighassuranceevrootca |  Apr 21, 2018 | 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25 | 
| secomvalicertclass1ca |  Apr 21, 2018 | E5:DF:74:3C:B6:01:C4:9B:98:43:DC:AB:8C:E8:6A:81:10:9F:E4:8E | 
| equifaxsecureglobalebusinessca1 |  Apr 21, 2018 | 3A:74:CB:7A:47:DB:70:DE:89:1F:24:35:98:64:B8:2D:82:BD:1A:36 | 
| geotrustuniversalca |  Apr 21, 2018 | E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79 | 
| deprecateditsecca |  Jan 27, 2012 | 12:12:0B:03:0E:15:14:54:F4:DD:B3:F5:DE:13:6E:83:5A:29:72:9D | 
| verisignclass3ca |  Apr 21, 2018 | A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B | 
| thawteprimaryrootcag3 |  Apr 21, 2018 | F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2 | 
| thawteprimaryrootcag2 |  Apr 21, 2018 | AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12 | 
| deutschetelekomrootca2 |  Apr 21, 2018 | 85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF | 
| buypassclass3ca |  Apr 21, 2018 | DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57 | 
| utnuserfirstobjectca |  Apr 21, 2018 | E1:2D:FB:4B:41:D7:D9:C3:2B:30:51:4B:AC:1D:81:D8:38:5E:2D:46 | 
| geotrustprimaryca |  Apr 21, 2018 | 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96 | 
| buypassclass2ca |  Apr 21, 2018 | 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99 | 
| baltimorecodesigningca |  Apr 21, 2018 | 30:46:D8:C8:88:FF:69:30:C3:4A:FC:CD:49:27:08:7C:60:56:7B:0D | 
| verisignclass1ca |  Apr 21, 2018 | CE:6A:64:A3:09:E4:2F:BB:D9:85:1C:45:3E:64:09:EA:E8:7D:60:F1 | 
| baltimorecybertrustca |  Apr 21, 2018 | D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 | 
| starfieldclass2ca |  Apr 21, 2018 | AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A | 
| camerfirmachamberscommerceca |  Apr 21, 2018 | 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1 | 
| ttelesecglobalrootclass3ca |  Apr 21, 2018 | 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 | 
| verisignclass3g5ca |  Apr 21, 2018 | 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 | 
| ttelesecglobalrootclass2ca |  Apr 21, 2018 | 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9 | 
| trustcenteruniversalcai |  Apr 21, 2018 | 6B:2F:34:AD:89:58:BE:62:FD:B0:6B:5C:CE:BB:9D:D9:4F:4E:39:F3 | 
| verisignclass3g4ca |  Apr 21, 2018 | 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A | 
| verisignclass3g3ca |  Apr 21, 2018 | 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 | 
| xrampglobalca |  Apr 21, 2018 | B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6 | 
| amzninternalrootca |  Dec 12, 2008 | A7:B7:F6:15:8A:FF:1E:C8:85:13:38:BC:93:EB:A2:AB:A4:09:EF:06 | 
| certplusclass3pprimaryca |  Apr 21, 2018 | 21:6B:2A:29:E6:2A:00:CE:82:01:46:D8:24:41:41:B9:25:11:B2:79 | 
| certumtrustednetworkca |  Apr 21, 2018 | 07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E | 
| verisignclass3g2ca |  Apr 21, 2018 | 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F | 
| globalsignr3ca |  Apr 21, 2018 | D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD | 
| utndatacorpsgcca |  Apr 21, 2018 | 58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4 | 
| secomscrootca2 |  Apr 21, 2018 | 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74 | 
| gtecybertrustglobalca |  Apr 21, 2018 | 97:81:79:50:D8:1C:96:70:CC:34:D8:09:CF:79:44:31:36:7E:F4:74 | 
| secomscrootca1 |  Apr 21, 2018 | 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7 | 
| affirmtrustcommercialca |  Apr 21, 2018 | F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7 | 
| trustcenterclass4caii |  Apr 21, 2018 | A6:9A:91:FD:05:7F:13:6A:42:63:0B:B1:76:0D:2D:51:12:0C:16:50 | 
| verisignuniversalrootca |  Apr 21, 2018 | 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 | 
| globalsignr2ca |  Apr 21, 2018 | 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE | 
| certplusclass2primaryca |  Apr 21, 2018 | 74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB | 
| digicertglobalrootca |  Apr 21, 2018 | A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36 | 
| globalsignca |  Apr 21, 2018 | B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C | 
| thawteprimaryrootca |  Apr 21, 2018 | 91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81 | 
| starfieldrootg2ca |  Apr 21, 2018 | B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E | 
| geotrustglobalca |  Apr 21, 2018 | DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12 | 
| soneraclass2ca |  Apr 21, 2018 | 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27 | 
| verisigntsaca |  Apr 21, 2018 | 20:CE:B1:F0:F5:1C:0E:19:A9:F3:8D:B1:AA:8E:03:8C:AA:7A:C7:01 | 
| soneraclass1ca |  Apr 21, 2018 | 07:47:22:01:99:CE:74:B9:7C:B0:3D:79:B2:64:A2:C8:55:E9:33:FF | 
| quovadisrootca |  Apr 21, 2018 | DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9 | 
| affirmtrustpremiumeccca |  Apr 21, 2018 | B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB | 
| starfieldservicesrootg2ca |  Apr 21, 2018 | 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F | 
| valicertclass2ca |  Apr 21, 2018 | 31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6 | 
| comodoaaaca |  Apr 21, 2018 | D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 | 
| aolrootca2 |  Apr 21, 2018 | 85:B5:FF:67:9B:0C:79:96:1F:C8:6E:44:22:00:46:13:DB:17:92:84 | 
| keynectisrootca |  Apr 21, 2018 | 9C:61:5C:4D:4D:85:10:3A:53:26:C2:4D:BA:EA:E4:A2:D2:D5:CC:97 | 
| addtrustqualifiedca |  Apr 21, 2018 | 4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E:C5:4D:8B:CF | 
| aolrootca1 |  Apr 21, 2018 | 39:21:C1:15:C1:5D:0E:CA:5C:CB:5B:C4:F0:7D:21:D8:05:0B:56:6A | 
| verisignclass2g3ca |  Apr 21, 2018 | 61:EF:43:D7:7F:CA:D4:61:51:BC:98:E0:C3:59:12:AF:9F:EB:63:11 | 
| addtrustexternalca |  Apr 21, 2018 | 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68 | 
| verisignclass2g2ca |  Apr 21, 2018 | B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9D | 
| geotrustprimarycag3 |  Apr 21, 2018 | 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD | 
| geotrustprimarycag2 |  Apr 21, 2018 | 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0 | 
| swisssigngoldg2ca |  Apr 21, 2018 | D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61 | 
| entrust2048ca |  Apr 21, 2018 | 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31 | 
| chunghwaepkirootca |  Apr 21, 2018 | 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0 | 
| camerfirmachambersignca |  Apr 21, 2018 | 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C | 
| camerfirmachambersca |  Apr 21, 2018 | 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C | 
| godaddyclass2ca |  Apr 21, 2018 | 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4 | 
| affirmtrustpremiumca |  Apr 21, 2018 | D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27 | 
| verisignclass1g3ca |  Apr 21, 2018 | 20:42:85:DC:F7:EB:76:41:95:57:8E:13:6B:D4:B7:D1:E9:8E:46:A5 | 
| secomevrootca1 |  Apr 21, 2018 | FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D | 
| verisignclass1g2ca |  Apr 21, 2018 | 27:3E:E1:24:57:FD:C4:F9:0C:55:E8:2B:56:16:7F:62:F5:32:E5:47 | 
| amzninternalinfoseccag3 |  Feb 27, 2015 | B9:B1:CA:38:F7:BF:9C:D2:D4:95:E7:B6:5E:75:32:9B:A8:78:2E:F6 | 
| cia-crt-g3-01-ca |  Nov 23, 2016 | 2B:EE:2C:BA:A3:1D:B5:FE:60:40:41:95:08:ED:46:82:39:4D:ED:E2 | 
| godaddyrootg2ca |  Apr 21, 2018 | 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B | 
| digicertassuredidrootca |  Apr 21, 2018 | 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43 | 
| microseceszignorootca2009 |  Apr 21, 2018 | 89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E | 
| affirmtrustcommercial |  Apr 21, 2018 | F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7 | 
| comodoecccertificationauthority |  Apr 21, 2018 | 9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11 | 
| cadisigrootr2 |  Apr 21, 2018 | B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71 | 
| swisssignsilvercag2 |  Apr 21, 2018 | 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB | 
| securetrustca |  Apr 21, 2018 | 87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11 | 
| cadisigrootr1 |  Apr 21, 2018 | 8E:1C:74:F8:A6:20:B9:E5:8A:F4:61:FA:EC:2B:47:56:51:1A:52:C6 | 
| accvraiz1 |  Apr 21, 2018 | 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17 | 
| entrustrootcertificationauthority |  Apr 21, 2018 | B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 | 
| camerfirmaglobalchambersignroot |  Apr 21, 2018 | 33:9B:6B:14:50:24:9B:55:7A:01:87:72:84:D9:E0:2F:C3:D2:D8:E9 | 
| dstacescax6 |  Apr 21, 2018 | 40:54:DA:6F:1C:3F:40:74:AC:ED:0F:EC:CD:DB:79:D1:53:FB:90:1D | 
| identrustpublicsectorrootca1 |  Apr 21, 2018 | BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD | 
| starfieldrootcertificateauthorityg2 |  Apr 21, 2018 | B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E | 
| secureglobalca |  Apr 21, 2018 | 3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B | 
| eecertificationcentrerootca |  Apr 21, 2018 | C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7 | 
| opentrustrootcag3 |  Apr 21, 2018 | 6E:26:64:F3:56:BF:34:55:BF:D1:93:3F:7C:01:DE:D8:13:DA:8A:A6 | 
| teliasonerarootcav1 |  Apr 21, 2018 | 43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37 | 
| autoridaddecertificacionfirmaprofesionalcifa62634068 |  Apr 21, 2018 | AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA | 
| opentrustrootcag2 |  Apr 21, 2018 | 79:5F:88:60:C5:AB:7C:3D:92:E6:CB:F4:8D:E1:45:CD:11:EF:60:0B | 
| opentrustrootcag1 |  Apr 21, 2018 | 79:91:E8:34:F7:E2:EE:DD:08:95:01:52:E9:55:2D:14:E9:58:D5:7E | 
| globalsigneccrootcar5 |  Apr 21, 2018 | 1F:24:C6:30:CD:A4:18:EF:20:69:FF:AD:4F:DD:5F:46:3A:1B:69:AA | 
| globalsigneccrootcar4 |  Apr 21, 2018 | 69:69:56:2E:40:80:F4:24:A1:E7:19:9F:14:BA:F3:EE:58:AB:6A:BB | 
| izenpecom |  Apr 21, 2018 | 2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19 | 
| turktrustelektroniksertifikahizmetsaglayicisih5 |  Apr 21, 2018 | C4:18:F6:4D:46:D1:DF:00:3D:27:30:13:72:43:A9:12:11:C6:75:FB | 
| gdcatrustauthr5root |  Apr 21, 2018 | 0F:36:38:5B:81:1A:25:C3:9B:31:4E:83:CA:E9:34:66:70:CC:74:B4 | 
| dtrustrootclass3ca22009 |  Apr 21, 2018 | 58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0 | 
| quovadisrootca3 |  Apr 21, 2018 | 1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85 | 
| quovadisrootca2 |  Apr 21, 2018 | CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7 | 
| geotrustprimarycertificationauthorityg3 |  Apr 21, 2018 | 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD | 
| geotrustprimarycertificationauthorityg2 |  Apr 21, 2018 | 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0 | 
| oistewisekeyglobalrootgbca |  Apr 21, 2018 | 0F:F9:40:76:18:D3:D7:6A:4B:98:F0:A8:35:9E:0C:FD:27:AC:CC:ED | 
| addtrustexternalroot |  Apr 21, 2018 | 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68 | 
| chambersofcommerceroot2008 |  Apr 21, 2018 | 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C | 
| digicertglobalrootg3 |  Apr 21, 2018 | 7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E | 
| comodoaaaservicesroot |  Apr 21, 2018 | D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 | 
| digicertglobalrootg2 |  Apr 21, 2018 | DF:3C:24:F9:BF:D6:66:76:1B:26:80:73:FE:06:D1:CC:8D:4F:82:A4 | 
| certinomisrootca |  Apr 21, 2018 | 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8 | 
| oistewisekeyglobalrootgaca |  Apr 21, 2018 | 59:22:A1:E1:5A:EA:16:35:21:F8:98:39:6A:46:46:B0:44:1B:0F:A9 | 
| dstrootcax3 |  Apr 21, 2018 | DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13 | 
| certigna |  Apr 21, 2018 | B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97 | 
| digicerthighassuranceevrootca |  Apr 21, 2018 | 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25 | 
| soneraclass2rootca |  Apr 21, 2018 | 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27 | 
| trustcorrootcertca2 |  Apr 21, 2018 | B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 | 
| usertrustrsacertificationauthority |  Apr 21, 2018 | 2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E | 
| trustcorrootcertca1 |  Apr 21, 2018 | FF:BD:CD:E7:82:C8:43:5E:3C:6F:26:86:5C:CA:A8:3A:45:5B:C3:0A | 
| geotrustuniversalca |  Apr 21, 2018 | E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79 | 
| certsignrootca |  Apr 21, 2018 | FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B | 
| amazonrootca4 |  Apr 21, 2018 | F6:10:84:07:D6:F8:BB:67:98:0C:C2:E2:44:C2:EB:AE:1C:EF:63:BE | 
| amazonrootca3 |  Apr 21, 2018 | 0D:44:DD:8C:3C:8C:1A:1A:58:75:64:81:E9:0F:2E:2A:FF:B3:D2:6E | 
| amazonrootca2 |  Apr 21, 2018 | 5A:8C:EF:45:D7:A6:98:59:76:7A:8C:8B:44:96:B5:78:CF:47:4B:1A | 
| verisignuniversalrootcertificationauthority |  Apr 21, 2018 | 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 | 
| amazonrootca1 |  Apr 21, 2018 | 8D:A7:F9:65:EC:5E:FC:37:91:0F:1C:6E:59:FD:C1:CC:6A:6E:DE:16 | 
| networksolutionscertificateauthority |  Apr 21, 2018 | 74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE | 
| thawteprimaryrootcag3 |  Apr 21, 2018 | F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2 | 
| affirmtrustnetworking |  Apr 21, 2018 | 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F | 
| thawteprimaryrootcag2 |  Apr 21, 2018 | AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12 | 
| trustcoreca1 |  Apr 21, 2018 | 58:D1:DF:95:95:67:6B:63:C0:F0:5B:1C:17:4D:8B:84:0B:C8:78:BD | 
| deutschetelekomrootca2 |  Apr 21, 2018 | 85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF | 
| godaddyrootcertificateauthorityg2 |  Apr 21, 2018 | 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B | 
| entrustrootcertificationauthorityec1 |  Apr 21, 2018 | 20:D8:06:40:DF:9B:25:F5:12:25:3A:11:EA:F7:59:8A:EB:14:B5:47 | 
| szafirrootca2 |  Apr 21, 2018 | E2:52:FA:95:3F:ED:DB:24:60:BD:6E:28:F3:9C:CC:CF:5E:B3:3F:DE | 
| tubitakkamusmsslkoksertifikasisurum1 |  Apr 21, 2018 | 31:43:64:9B:EC:CE:27:EC:ED:3A:3F:0B:8F:0D:E4:E8:91:DD:EE:CA | 
| buypassclass3rootca |  Apr 21, 2018 | DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57 | 
| comodorsacertificationauthority |  Apr 21, 2018 | AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4 | 
| netlockaranyclassgoldfotanusitvany |  Apr 21, 2018 | 06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91 | 
| securitycommunicationrootca2 |  Apr 21, 2018 | 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74 | 
| dtrustrootclass3ca2ev2009 |  Apr 21, 2018 | 96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83 | 
| starfieldclass2ca |  Apr 21, 2018 | AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A | 
| pscprocert |  Apr 21, 2018 | 70:C1:8D:74:B4:28:81:0A:E4:FD:A5:75:D7:01:9F:99:B0:3D:50:74 | 
| actalisauthenticationrootca |  Apr 21, 2018 | F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC | 
| staatdernederlandenrootcag3 |  Apr 21, 2018 | D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC | 
| cfcaevroot |  Apr 21, 2018 | E2:B8:29:4B:55:84:AB:6B:58:C2:90:46:6C:AC:3F:B8:39:8F:84:83 | 
| digicerttrustedrootg4 |  Apr 21, 2018 | DD:FB:16:CD:49:31:C9:73:A2:03:7D:3F:C8:3A:4D:7D:77:5D:05:E4 | 
| staatdernederlandenrootcag2 |  Apr 21, 2018 | 59:AF:82:79:91:86:C7:B4:75:07:CB:CF:03:57:46:EB:04:DD:B7:16 | 
| securitycommunicationevrootca1 |  Apr 21, 2018 | FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D | 
| globalsignrootcar3 |  Apr 21, 2018 | D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD | 
| globalsignrootcar2 |  Apr 21, 2018 | 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE | 
| certumtrustednetworkca2 |  Apr 21, 2018 | D3:DD:48:3E:2B:BF:4C:05:E8:AF:10:F5:FA:76:26:CF:D3:DC:30:92 | 
| acraizfnmtrcm |  Apr 21, 2018 | EC:50:35:07:B2:15:C4:95:62:19:E2:A8:9A:5B:42:99:2C:4C:2C:20 | 
| hellenicacademicandresearchinstitutionseccrootca2015 |  Apr 21, 2018 | 9F:F1:71:8D:92:D5:9A:F3:7D:74:97:B4:BC:6F:84:68:0B:BA:B6:66 | 
| certplusrootcag2 |  Apr 21, 2018 | 4F:65:8E:1F:E9:06:D8:28:02:E9:54:47:41:C9:54:25:5D:69:CC:1A | 
| twcarootcertificationauthority |  Apr 21, 2018 | CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48 | 
| twcaglobalrootca |  Apr 21, 2018 | 9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65 | 
| certplusrootcag1 |  Apr 21, 2018 | 22:FD:D0:B7:FD:A2:4E:0D:AC:49:2C:A0:AC:A6:7B:6A:1F:E3:F7:66 | 
| geotrustuniversalca2 |  Apr 21, 2018 | 37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79 | 
| baltimorecybertrustroot |  Apr 21, 2018 | D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 | 
| buypassclass2rootca |  Apr 21, 2018 | 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99 | 
| certumtrustednetworkca |  Apr 21, 2018 | 07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E | 
| digicertassuredidrootg3 |  Apr 21, 2018 | F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89 | 
| digicertassuredidrootg2 |  Apr 21, 2018 | A1:4B:48:D9:43:EE:0A:0E:40:90:4F:3C:E0:A4:C0:91:93:51:5D:3F | 
| isrgrootx1 |  Apr 21, 2018 | CA:BD:2A:79:A1:07:6A:31:F2:1D:25:36:35:CB:03:9D:43:29:A5:E8 | 
| entrustnetpremium2048secureserverca |  Apr 21, 2018 | 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31 | 
| certplusclass2primaryca |  Apr 21, 2018 | 74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB | 
| digicertglobalrootca |  Apr 21, 2018 | A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36 | 
| entrustrootcertificationauthorityg2 |  Apr 21, 2018 | 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4 | 
| starfieldservicesrootcertificateauthorityg2 |  Apr 21, 2018 | 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F | 
| thawteprimaryrootca |  Apr 21, 2018 | 91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81 | 
| atostrustedroot2011 |  Apr 21, 2018 | 2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21 | 
| geotrustglobalca |  Apr 21, 2018 | DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12 | 
| luxtrustglobalroot2 |  Apr 21, 2018 | 1E:0E:56:19:0A:D1:8B:25:98:B2:04:44:FF:66:8A:04:17:99:5F:3F | 
| etugracertificationauthority |  Apr 21, 2018 | 51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39 | 
| visaecommerceroot |  Apr 21, 2018 | 70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62 | 
| quovadisrootca |  Apr 21, 2018 | DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9 | 
| identrustcommercialrootca1 |  Apr 21, 2018 | DF:71:7E:AA:4A:D9:4E:C9:55:84:99:60:2D:48:DE:5F:BC:F0:3A:25 | 
| staatdernederlandenevrootca |  Apr 21, 2018 | 76:E2:7E:C1:4F:DB:82:C1:C0:A6:75:B5:05:BE:3D:29:B4:ED:DB:BB | 
| ttelesecglobalrootclass3 |  Apr 21, 2018 | 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 | 
| ttelesecglobalrootclass2 |  Apr 21, 2018 | 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9 | 
| comodocertificationauthority |  Apr 21, 2018 | 66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B | 
| securitycommunicationrootca |  Apr 21, 2018 | 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7 | 
| quovadisrootca3g3 |  Apr 21, 2018 | 48:12:BD:92:3C:A8:C4:39:06:E7:30:6D:27:96:E6:A4:CF:22:2E:7D | 
| xrampglobalcaroot |  Apr 21, 2018 | B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6 | 
| securesignrootca11 |  Apr 21, 2018 | 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3 | 
| affirmtrustpremium |  Apr 21, 2018 | D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27 | 
| globalsignrootca |  Apr 21, 2018 | B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C | 
| swisssigngoldcag2 |  Apr 21, 2018 | D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61 | 
| quovadisrootca2g3 |  Apr 21, 2018 | 09:3C:61:F3:8B:8B:DC:7D:55:DF:75:38:02:05:00:E1:25:F5:C8:36 | 
| affirmtrustpremiumecc |  Apr 21, 2018 | B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB | 
| geotrustprimarycertificationauthority |  Apr 21, 2018 | 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96 | 
| quovadisrootca1g3 |  Apr 21, 2018 | 1B:8E:EA:57:96:29:1A:C9:39:EA:B8:0A:81:1A:73:73:C0:93:79:67 | 
| hongkongpostrootca1 |  Apr 21, 2018 | D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58 | 
| usertrustecccertificationauthority |  Apr 21, 2018 | D1:CB:CA:5D:B2:D5:2A:7F:69:3B:67:4D:E5:F0:5A:1D:0C:95:7D:F0 | 
| cybertrustglobalroot |  Apr 21, 2018 | 5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6 | 
| godaddyclass2ca |  Apr 21, 2018 | 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4 | 
| hellenicacademicandresearchinstitutionsrootca2015 |  Apr 21, 2018 | 01:0C:06:95:A6:98:19:14:FF:BF:5F:C6:B0:B6:95:EA:29:E9:12:A6 | 
| ecacc |  Apr 21, 2018 | 28:90:3A:63:5B:52:80:FA:E6:77:4C:0B:6D:A7:D6:BA:A6:4A:F2:E8 | 
| hellenicacademicandresearchinstitutionsrootca2011 |  Apr 21, 2018 | FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D | 
| verisignclass3publicprimarycertificationauthorityg5 |  Apr 21, 2018 | 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 | 
| verisignclass3publicprimarycertificationauthorityg4 |  Apr 21, 2018 | 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A | 
| verisignclass3publicprimarycertificationauthorityg3 |  Apr 21, 2018 | 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 | 
| trustisfpsrootca |  Apr 21, 2018 | 3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04 | 
| epkirootcertificationauthority |  Apr 21, 2018 | 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0 | 
| globalchambersignroot2008 |  Apr 21, 2018 | 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C | 
| camerfirmachambersofcommerceroot |  Apr 21, 2018 | 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1 | 
| mozillacert81.pem |  Mar 13, 2014 | 07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E | 
| mozillacert99.pem |  Mar 13, 2014 | F1:7F:6F:B6:31:DC:99:E3:A3:C8:7F:FE:1C:F1:81:10:88:D9:60:33 | 
| mozillacert145.pem |  Mar 13, 2014 | 10:1D:FA:3F:D5:0B:CB:BB:9B:B5:60:0C:19:55:A4:1A:F4:73:3A:04 | 
| mozillacert37.pem |  Mar 13, 2014 | B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97 | 
| mozillacert4.pem |  Mar 13, 2014 | E3:92:51:2F:0A:CF:F5:05:DF:F6:DE:06:7F:75:37:E1:65:EA:57:4B | 
| mozillacert70.pem |  Mar 13, 2014 | 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C | 
| mozillacert88.pem |  Mar 13, 2014 | FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D | 
| mozillacert134.pem |  Mar 13, 2014 | 70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62 | 
| mozillacert26.pem |  Mar 13, 2014 | 87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11 | 
| mozillacert77.pem |  Mar 13, 2014 | 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 | 
| mozillacert123.pem |  Mar 13, 2014 | 2A:B6:28:48:5E:78:FB:F3:AD:9E:79:10:DD:6B:DF:99:72:2C:96:E5 | 
| mozillacert15.pem |  Mar 13, 2014 | 74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB | 
| mozillacert66.pem |  Mar 13, 2014 | DD:E1:D2:A9:01:80:2E:1D:87:5E:84:B3:80:7E:4B:B1:FD:99:41:34 | 
| mozillacert112.pem |  Mar 13, 2014 | 43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37 | 
| mozillacert55.pem |  Mar 13, 2014 | AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12 | 
| mozillacert101.pem |  Mar 13, 2014 | 99:A6:9B:E6:1A:FE:88:6B:4D:2B:82:00:7C:B8:54:FC:31:7E:15:39 | 
| mozillacert119.pem |  Mar 13, 2014 | 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE | 
| mozillacert44.pem |  Mar 13, 2014 | 5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6 | 
| mozillacert108.pem |  Mar 13, 2014 | B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C | 
| mozillacert95.pem |  Mar 13, 2014 | DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57 | 
| mozillacert141.pem |  Mar 13, 2014 | 31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6 | 
| mozillacert33.pem |  Mar 13, 2014 | FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D | 
| mozillacert0.pem |  Mar 13, 2014 | 97:81:79:50:D8:1C:96:70:CC:34:D8:09:CF:79:44:31:36:7E:F4:74 | 
| mozillacert84.pem |  Mar 13, 2014 | D3:C0:63:F2:19:ED:07:3E:34:AD:5D:75:0B:32:76:29:FF:D5:9A:F2 | 
| mozillacert130.pem |  Mar 13, 2014 | E5:DF:74:3C:B6:01:C4:9B:98:43:DC:AB:8C:E8:6A:81:10:9F:E4:8E | 
| mozillacert148.pem |  Mar 13, 2014 | 04:83:ED:33:99:AC:36:08:05:87:22:ED:BC:5E:46:00:E3:BE:F9:D7 | 
| mozillacert22.pem |  Mar 13, 2014 | 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96 | 
| mozillacert7.pem |  Mar 13, 2014 | AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A | 
| mozillacert73.pem |  Mar 13, 2014 | B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E | 
| mozillacert137.pem |  Mar 13, 2014 | 4A:65:D5:F4:1D:EF:39:B8:B8:90:4A:4A:D3:64:81:33:CF:C7:A1:D1 | 
| mozillacert11.pem |  Mar 13, 2014 | 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43 | 
| mozillacert29.pem |  Mar 13, 2014 | 74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE | 
| mozillacert62.pem |  Mar 13, 2014 | A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B | 
| mozillacert126.pem |  Mar 13, 2014 | 25:01:90:19:CF:FB:D9:99:1C:B7:68:25:74:8D:94:5F:30:93:95:42 | 
| mozillacert18.pem |  Mar 13, 2014 | 79:98:A3:08:E1:4D:65:85:E6:C2:1E:15:3A:71:9F:BA:5A:D3:4A:D9 | 
| mozillacert51.pem |  Mar 13, 2014 | FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B | 
| mozillacert69.pem |  Mar 13, 2014 | 2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19 | 
| mozillacert115.pem |  Mar 13, 2014 | 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9 | 
| mozillacert40.pem |  Mar 13, 2014 | 80:25:EF:F4:6E:70:C8:D4:72:24:65:84:FE:40:3B:8A:8D:6A:DB:F5 | 
| mozillacert58.pem |  Mar 13, 2014 | 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0 | 
| mozillacert104.pem |  Mar 13, 2014 | 4F:99:AA:93:FB:2B:D1:37:26:A1:99:4A:CE:7F:F0:05:F2:93:5D:1E | 
| mozillacert91.pem |  Mar 13, 2014 | 3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04 | 
| mozillacert47.pem |  Mar 13, 2014 | 1B:4B:39:61:26:27:6B:64:91:A2:68:6D:D7:02:43:21:2D:1F:1D:96 | 
| mozillacert80.pem |  Mar 13, 2014 | B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB | 
| mozillacert98.pem |  Mar 13, 2014 | C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7 | 
| mozillacert144.pem |  Mar 13, 2014 | 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27 | 
| mozillacert36.pem |  Mar 13, 2014 | 23:88:C9:D3:71:CC:9E:96:3D:FF:7D:3C:A7:CE:FC:D6:25:EC:19:0D | 
| mozillacert3.pem |  Mar 13, 2014 | 87:9F:4B:EE:05:DF:98:58:3B:E3:60:D6:33:E7:0D:3F:FE:98:71:AF | 
| mozillacert87.pem |  Mar 13, 2014 | 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74 | 
| mozillacert133.pem |  Mar 13, 2014 | 85:B5:FF:67:9B:0C:79:96:1F:C8:6E:44:22:00:46:13:DB:17:92:84 | 
| mozillacert25.pem |  Mar 13, 2014 | 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 | 
| mozillacert76.pem |  Mar 13, 2014 | F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7 | 
| mozillacert122.pem |  Mar 13, 2014 | 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68 | 
| mozillacert14.pem |  Mar 13, 2014 | 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25 | 
| mozillacert65.pem |  Mar 13, 2014 | 69:BD:8C:F4:9C:D3:00:FB:59:2E:17:93:CA:55:6A:F3:EC:AA:35:FB | 
| mozillacert111.pem |  Mar 13, 2014 | 9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65 | 
| mozillacert129.pem |  Mar 13, 2014 | E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79 | 
| mozillacert54.pem |  Mar 13, 2014 | 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD | 
| mozillacert100.pem |  Mar 13, 2014 | 58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0 | 
| mozillacert118.pem |  Mar 13, 2014 | 7E:78:4A:10:1C:82:65:CC:2D:E1:F1:6D:47:B4:40:CA:D9:0A:19:45 | 
| mozillacert151.pem |  Mar 13, 2014 | AC:ED:5F:65:53:FD:25:CE:01:5F:1F:7A:48:3B:6A:74:9F:61:78:C6 | 
| mozillacert43.pem |  Mar 13, 2014 | F9:CD:0E:2C:DA:76:24:C1:8F:BD:F0:F0:AB:B6:45:B8:F7:FE:D5:7A | 
| mozillacert107.pem |  Mar 13, 2014 | 8E:1C:74:F8:A6:20:B9:E5:8A:F4:61:FA:EC:2B:47:56:51:1A:52:C6 | 
| mozillacert94.pem |  Mar 13, 2014 | 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99 | 
| mozillacert140.pem |  Mar 13, 2014 | CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7 | 
| mozillacert32.pem |  Mar 13, 2014 | 60:D6:89:74:B5:C2:65:9E:8A:0F:C1:88:7C:88:D2:46:69:1B:18:2C | 
| mozillacert83.pem |  Mar 13, 2014 | A0:73:E5:C5:BD:43:61:0D:86:4C:21:13:0A:85:58:57:CC:9C:EA:46 | 
| mozillacert147.pem |  Mar 13, 2014 | 58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4 | 
| mozillacert21.pem |  Mar 13, 2014 | 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB | 
| mozillacert39.pem |  Mar 13, 2014 | AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E | 
| mozillacert6.pem |  Mar 13, 2014 | 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4 | 
| mozillacert72.pem |  Mar 13, 2014 | 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B | 
| mozillacert136.pem |  Mar 13, 2014 | D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 | 
| mozillacert10.pem |  Mar 13, 2014 | 5F:3A:FC:0A:8B:64:F6:86:67:34:74:DF:7E:A9:A2:FE:F9:FA:7A:51 | 
| mozillacert28.pem |  Mar 13, 2014 | 66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B | 
| mozillacert61.pem |  Mar 13, 2014 | E0:B4:32:2E:B2:F6:A5:68:B6:54:53:84:48:18:4A:50:36:87:43:84 | 
| mozillacert79.pem |  Mar 13, 2014 | D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27 | 
| mozillacert125.pem |  Mar 13, 2014 | B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 | 
| mozillacert17.pem |  Mar 13, 2014 | 40:54:DA:6F:1C:3F:40:74:AC:ED:0F:EC:CD:DB:79:D1:53:FB:90:1D | 
| mozillacert50.pem |  Mar 13, 2014 | 8C:96:BA:EB:DD:2B:07:07:48:EE:30:32:66:A0:F3:98:6E:7C:AE:58 | 
| mozillacert68.pem |  Mar 13, 2014 | AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA | 
| mozillacert114.pem |  Mar 13, 2014 | 51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39 | 
| mozillacert57.pem |  Mar 13, 2014 | D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58 | 
| mozillacert103.pem |  Mar 13, 2014 | 70:C1:8D:74:B4:28:81:0A:E4:FD:A5:75:D7:01:9F:99:B0:3D:50:74 | 
| mozillacert90.pem |  Mar 13, 2014 | F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC | 
| mozillacert46.pem |  Mar 13, 2014 | 40:9D:4B:D9:17:B5:5C:27:B6:9B:64:CB:98:22:44:0D:CD:09:B8:89 | 
| mozillacert97.pem |  Mar 13, 2014 | 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F | 
| mozillacert143.pem |  Mar 13, 2014 | 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7 | 
| mozillacert35.pem |  Mar 13, 2014 | 2A:C8:D5:8B:57:CE:BF:2F:49:AF:F2:FC:76:8F:51:14:62:90:7A:41 | 
| mozillacert2.pem |  Mar 13, 2014 | 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A | 
| mozillacert86.pem |  Mar 13, 2014 | 74:2C:31:92:E6:07:E4:24:EB:45:49:54:2B:E1:BB:C5:3E:61:74:E2 | 
| mozillacert132.pem |  Mar 13, 2014 | 39:21:C1:15:C1:5D:0E:CA:5C:CB:5B:C4:F0:7D:21:D8:05:0B:56:6A | 
| mozillacert24.pem |  Mar 13, 2014 | 59:AF:82:79:91:86:C7:B4:75:07:CB:CF:03:57:46:EB:04:DD:B7:16 | 
| mozillacert9.pem |  Mar 13, 2014 | F4:8B:11:BF:DE:AB:BE:94:54:20:71:E6:41:DE:6B:BE:88:2B:40:B9 | 
| mozillacert75.pem |  Mar 13, 2014 | D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A | 
| mozillacert121.pem |  Mar 13, 2014 | CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D | 
| mozillacert139.pem |  Mar 13, 2014 | DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9 | 
| mozillacert13.pem |  Mar 13, 2014 | 06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91 | 
| mozillacert64.pem |  Mar 13, 2014 | 62:7F:8D:78:27:65:63:99:D2:7D:7F:90:44:C9:FE:B3:F3:3E:FA:9A | 
| mozillacert110.pem |  Mar 13, 2014 | 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17 | 
| mozillacert128.pem |  Mar 13, 2014 | A9:E9:78:08:14:37:58:88:F2:05:19:B0:6D:2B:0D:2B:60:16:90:7D | 
| mozillacert53.pem |  Mar 13, 2014 | 7F:8A:B0:CF:D0:51:87:6A:66:F3:36:0F:47:C8:8D:8C:D3:35:FC:74 | 
| mozillacert117.pem |  Mar 13, 2014 | D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 | 
| mozillacert150.pem |  Mar 13, 2014 | 33:9B:6B:14:50:24:9B:55:7A:01:87:72:84:D9:E0:2F:C3:D2:D8:E9 | 
| mozillacert42.pem |  Mar 13, 2014 | 85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF | 
| mozillacert106.pem |  Mar 13, 2014 | E7:A1:90:29:D3:D5:52:DC:0D:0F:C6:92:D3:EA:88:0D:15:2E:1A:6B | 
| mozillacert93.pem |  Mar 13, 2014 | 31:F1:FD:68:22:63:20:EE:C6:3B:3F:9D:EA:4A:3E:53:7C:7C:39:17 | 
| mozillacert31.pem |  Mar 13, 2014 | 9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11 | 
| mozillacert49.pem |  Mar 13, 2014 | 61:57:3A:11:DF:0E:D8:7E:D5:92:65:22:EA:D0:56:D7:44:B3:23:71 | 
| mozillacert82.pem |  Mar 13, 2014 | 2E:14:DA:EC:28:F0:FA:1E:8E:38:9A:4E:AB:EB:26:C0:0A:D3:83:C3 | 
| mozillacert146.pem |  Mar 13, 2014 | 21:FC:BD:8E:7F:6C:AF:05:1B:D1:B3:43:EC:A8:E7:61:47:F2:0F:8A | 
| mozillacert20.pem |  Mar 13, 2014 | D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61 | 
| mozillacert38.pem |  Mar 13, 2014 | CB:A1:C5:F8:B0:E3:5E:B8:B9:45:12:D3:F9:34:A2:E9:06:10:D3:36 | 
| mozillacert5.pem |  Mar 13, 2014 | B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6 | 
| mozillacert71.pem |  Mar 13, 2014 | 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C | 
| mozillacert89.pem |  Mar 13, 2014 | C8:EC:8C:87:92:69:CB:4B:AB:39:E9:8D:7E:57:67:F3:14:95:73:9D | 
| mozillacert135.pem |  Mar 13, 2014 | 62:52:DC:40:F7:11:43:A2:2F:DE:9E:F7:34:8E:06:42:51:B1:81:18 | 
| mozillacert27.pem |  Mar 13, 2014 | 3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B | 
| mozillacert60.pem |  Mar 13, 2014 | 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3 | 
| mozillacert78.pem |  Mar 13, 2014 | 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F | 
| mozillacert124.pem |  Mar 13, 2014 | 4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E:C5:4D:8B:CF | 
| mozillacert16.pem |  Mar 13, 2014 | DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13 | 
| mozillacert67.pem |  Mar 13, 2014 | D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD | 
| mozillacert113.pem |  Mar 13, 2014 | 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31 | 
| mozillacert56.pem |  Mar 13, 2014 | F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2 | 
| mozillacert102.pem |  Mar 13, 2014 | 96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83 | 
| mozillacert45.pem |  Mar 13, 2014 | 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0 | 
| mozillacert109.pem |  Mar 13, 2014 | B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71 | 
| mozillacert96.pem |  Mar 13, 2014 | 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 | 
| mozillacert142.pem |  Mar 13, 2014 | 1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85 | 
| mozillacert34.pem |  Mar 13, 2014 | 59:22:A1:E1:5A:EA:16:35:21:F8:98:39:6A:46:46:B0:44:1B:0F:A9 | 
| mozillacert1.pem |  Mar 13, 2014 | 23:E5:94:94:51:95:F2:41:48:03:B4:D5:64:D2:A3:A3:F5:D8:8B:8C | 
| mozillacert85.pem |  Mar 13, 2014 | CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48 | 
| mozillacert131.pem |  Mar 13, 2014 | 37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79 | 
| mozillacert149.pem |  Mar 13, 2014 | 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1 | 
| mozillacert23.pem |  Mar 13, 2014 | 91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81 | 
| mozillacert8.pem |  Mar 13, 2014 | 3E:2B:F7:F2:03:1B:96:F3:8C:E6:C4:D8:A8:5D:3E:2D:58:47:6A:0F | 
| mozillacert74.pem |  Mar 13, 2014 | 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F | 
| mozillacert120.pem |  Mar 13, 2014 | DA:40:18:8B:91:89:A3:ED:EE:AE:DA:97:FE:2F:9D:F5:B7:D1:8A:41 | 
| mozillacert138.pem |  Mar 13, 2014 | E1:9F:E3:0E:8B:84:60:9E:80:9B:17:0D:72:A8:C5:BA:6E:14:09:BD | 
| mozillacert12.pem |  Mar 13, 2014 | A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36 | 
| mozillacert63.pem |  Mar 13, 2014 | 89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E | 
| mozillacert127.pem |  Mar 13, 2014 | DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12 | 
| mozillacert19.pem |  Mar 13, 2014 | B4:35:D4:E1:11:9D:1C:66:90:A7:49:EB:B3:94:BD:63:7B:A7:82:B7 | 
| mozillacert52.pem |  Mar 13, 2014 | 8B:AF:4C:9B:1D:F0:2A:92:F7:DA:12:8E:B9:1B:AC:F4:98:60:4B:6F | 
| mozillacert116.pem |  Mar 13, 2014 | 2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21 | 
| mozillacert41.pem |  Mar 13, 2014 | 6B:2F:34:AD:89:58:BE:62:FD:B0:6B:5C:CE:BB:9D:D9:4F:4E:39:F3 | 
| mozillacert59.pem |  Mar 13, 2014 | 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 | 
| mozillacert105.pem |  Mar 13, 2014 | 77:47:4F:C6:30:E4:0F:4C:47:64:3F:84:BA:B8:C6:95:4A:8A:41:EC | 
| mozillacert92.pem |  Mar 13, 2014 | A3:F1:33:3F:E2:42:BF:CF:C5:D1:4E:8F:39:42:98:40:68:10:D1:A0 | 
| mozillacert30.pem |  Mar 13, 2014 | E7:B4:F6:9D:61:EC:90:69:DB:7E:90:A7:40:1A:3C:F4:7D:4F:E8:EE | 
| mozillacert48.pem |  Mar 13, 2014 | A0:A1:AB:90:C9:FC:84:7B:3B:12:61:E8:97:7D:5F:D3:22:61:D3:CC | 
| verisignc4g2.pem |  Mar 20, 2014 | 0B:77:BE:BB:CB:7A:A2:47:05:DE:CC:0F:BD:6A:02:FC:7A:BD:9B:52 | 
| verisignc2g3.pem |  Mar 20, 2014 | 61:EF:43:D7:7F:CA:D4:61:51:BC:98:E0:C3:59:12:AF:9F:EB:63:11 | 
| verisignc1g6.pem |  Dec 31, 2014 | 51:7F:61:1E:29:91:6B:53:82:FB:72:E7:44:D9:8D:C3:CC:53:6D:64 | 
| verisignc2g2.pem |  Mar 20, 2014 | B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9D | 
| verisignroot.pem |  Mar 20, 2014 | 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 | 
| verisignc2g1.pem |  Mar 20, 2014 | 67:82:AA:E0:ED:EE:E2:1A:58:39:D3:C0:CD:14:68:0A:4F:60:14:2A | 
| verisignc3g5.pem |  Mar 20, 2014 | 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 | 
| verisignc1g3.pem |  Mar 20, 2014 | 20:42:85:DC:F7:EB:76:41:95:57:8E:13:6B:D4:B7:D1:E9:8E:46:A5 | 
| verisignc3g4.pem |  Mar 20, 2014 | 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A | 
| verisignc1g2.pem |  Mar 20, 2014 | 27:3E:E1:24:57:FD:C4:F9:0C:55:E8:2B:56:16:7F:62:F5:32:E5:47 | 
| verisignc3g3.pem |  Mar 20, 2014 | 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 | 
| verisignc1g1.pem |  Mar 20, 2014 | 90:AE:A2:69:85:FF:14:80:4C:43:49:52:EC:E9:60:84:77:AF:55:6F | 
| verisignc3g2.pem |  Mar 20, 2014 | 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F | 
| verisignc3g1.pem |  Mar 20, 2014 | A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B | 
| verisignc2g6.pem |  Dec 31, 2014 | 40:B3:31:A0:E9:BF:E8:55:BC:39:93:CA:70:4F:4E:C2:51:D4:1D:8F | 
| verisignc4g3.pem |  Mar 20, 2014 | C8:EC:8C:87:92:69:CB:4B:AB:39:E9:8D:7E:57:67:F3:14:95:73:9D | 
| gdroot-g2.pem |  Dec 31, 2014 | 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B | 
| gd-class2-root.pem |  Dec 31, 2014 | 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4 | 
| gd\$1bundle-g2.pem |  Dec 31, 2014 | 27:AC:93:69:FA:F2:52:07:BB:26:27:CE:FA:CC:BE:4E:F9:C3:19:B8 | 
| dstacescax6 |  Jun 18, 2018 | 40:54:DA:6F:1C:3F:40:74:AC:ED:0F:EC:CD:DB:79:D1:53:FB:90:1D | 
| gd\$1bundle-g2.pem |  Jun 18, 2018 | 27:AC:93:69:FA:F2:52:07:BB:26:27:CE:FA:CC:BE:4E:F9:C3:19:B8 | 
| verisignc4g3.pem |  Jun 18, 2018 | C8:EC:8C:87:92:69:CB:4B:AB:39:E9:8D:7E:57:67:F3:14:95:73:9D | 
| swisssignplatinumg2ca |  Apr 21, 2018 | 56:E0:FA:C0:3B:8F:18:23:55:18:E5:D3:11:CA:E8:C2:43:31:AB:66 | 
| geotrustprimarycertificationauthorityg3 |  Jun 18, 2018 | 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD | 
| geotrustprimarycertificationauthorityg2 |  Jun 18, 2018 | 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0 | 
| buypassclass2rootca |  Jun 18, 2018 | 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99 | 
| camerfirmachambersofcommerceroot |  Jun 18, 2018 | 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1 | 
| mozillacert20.pem |  Jun 18, 2018 | D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61 | 
| mozillacert12.pem |  Jun 18, 2018 | A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36 | 
| mozillacert90.pem |  Jun 18, 2018 | F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC | 
| mozillacert82.pem |  Jun 18, 2018 | 2E:14:DA:EC:28:F0:FA:1E:8E:38:9A:4E:AB:EB:26:C0:0A:D3:83:C3 | 
| mozillacert140.pem |  Jun 18, 2018 | CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7 | 
| mozillacert74.pem |  Jun 18, 2018 | 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F | 
| mozillacert132.pem |  Jun 18, 2018 | 39:21:C1:15:C1:5D:0E:CA:5C:CB:5B:C4:F0:7D:21:D8:05:0B:56:6A | 
| mozillacert66.pem |  Jun 18, 2018 | DD:E1:D2:A9:01:80:2E:1D:87:5E:84:B3:80:7E:4B:B1:FD:99:41:34 | 
| mozillacert124.pem |  Jun 18, 2018 | 4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E:C5:4D:8B:CF | 
| mozillacert58.pem |  Jun 18, 2018 | 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0 | 
| securitycommunicationrootca2 |  Jun 18, 2018 | 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74 | 
| mozillacert116.pem |  Jun 18, 2018 | 2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21 | 
| mozillacert108.pem |  Jun 18, 2018 | B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C | 
| certigna |  Jun 18, 2018 | B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97 | 
| mozillacert3.pem |  Jun 18, 2018 | 87:9F:4B:EE:05:DF:98:58:3B:E3:60:D6:33:E7:0D:3F:FE:98:71:AF | 
| verisignc1g1.pem |  Jun 18, 2018 | 90:AE:A2:69:85:FF:14:80:4C:43:49:52:EC:E9:60:84:77:AF:55:6F | 
| verisignc4g2.pem |  Jun 18, 2018 | 0B:77:BE:BB:CB:7A:A2:47:05:DE:CC:0F:BD:6A:02:FC:7A:BD:9B:52 | 
| deutschetelekomrootca2 |  Jun 18, 2018 | 85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF | 
| starfieldrootg2ca |  Apr 21, 2018 | B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E | 
| comodoecccertificationauthority |  Jun 18, 2018 | 9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11 | 
| digicertglobalrootg3 |  Jun 18, 2018 | 7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E | 
| digicertglobalrootg2 |  Jun 18, 2018 | DF:3C:24:F9:BF:D6:66:76:1B:26:80:73:FE:06:D1:CC:8D:4F:82:A4 | 
| mozillacert11.pem |  Jun 18, 2018 | 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43 | 
| mozillacert81.pem |  Jun 18, 2018 | 07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E | 
| mozillacert73.pem |  Jun 18, 2018 | B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E | 
| szafirrootca2 |  Jun 18, 2018 | E2:52:FA:95:3F:ED:DB:24:60:BD:6E:28:F3:9C:CC:CF:5E:B3:3F:DE | 
| mozillacert131.pem |  Jun 18, 2018 | 37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79 | 
| ecacc |  Jun 18, 2018 | 28:90:3A:63:5B:52:80:FA:E6:77:4C:0B:6D:A7:D6:BA:A6:4A:F2:E8 | 
| mozillacert65.pem |  Jun 18, 2018 | 69:BD:8C:F4:9C:D3:00:FB:59:2E:17:93:CA:55:6A:F3:EC:AA:35:FB | 
| turktrustelektroniksertifikahizmetsaglayicisih5 |  Jun 18, 2018 | C4:18:F6:4D:46:D1:DF:00:3D:27:30:13:72:43:A9:12:11:C6:75:FB | 
| mozillacert123.pem |  Jun 18, 2018 | 2A:B6:28:48:5E:78:FB:F3:AD:9E:79:10:DD:6B:DF:99:72:2C:96:E5 | 
| mozillacert57.pem |  Jun 18, 2018 | D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58 | 
| mozillacert115.pem |  Jun 18, 2018 | 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9 | 
| mozillacert49.pem |  Jun 18, 2018 | 61:57:3A:11:DF:0E:D8:7E:D5:92:65:22:EA:D0:56:D7:44:B3:23:71 | 
| mozillacert107.pem |  Jun 18, 2018 | 8E:1C:74:F8:A6:20:B9:E5:8A:F4:61:FA:EC:2B:47:56:51:1A:52:C6 | 
| verisignclass3g4ca |  Apr 21, 2018 | 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A | 
| securetrustca |  Jun 18, 2018 | 87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11 | 
| mozillacert2.pem |  Jun 18, 2018 | 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A | 
| buypassclass2ca |  Apr 21, 2018 | 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99 | 
| secomscrootca2 |  Apr 21, 2018 | 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74 | 
| secomscrootca1 |  Apr 21, 2018 | 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7 | 
| trustisfpsrootca |  Jun 18, 2018 | 3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04 | 
| hongkongpostrootca1 |  Jun 18, 2018 | D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58 | 
| certsignrootca |  Jun 18, 2018 | FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B | 
| geotrustprimaryca |  Apr 21, 2018 | 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96 | 
| twcaglobalrootca |  Jun 18, 2018 | 9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65 | 
| camerfirmachambersca |  Apr 21, 2018 | 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C | 
| mozillacert10.pem |  Jun 18, 2018 | 5F:3A:FC:0A:8B:64:F6:86:67:34:74:DF:7E:A9:A2:FE:F9:FA:7A:51 | 
| mozillacert80.pem |  Jun 18, 2018 | B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB | 
| mozillacert72.pem |  Jun 18, 2018 | 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B | 
| comodoaaaca |  Apr 21, 2018 | D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 | 
| mozillacert130.pem |  Jun 18, 2018 | E5:DF:74:3C:B6:01:C4:9B:98:43:DC:AB:8C:E8:6A:81:10:9F:E4:8E | 
| mozillacert64.pem |  Jun 18, 2018 | 62:7F:8D:78:27:65:63:99:D2:7D:7F:90:44:C9:FE:B3:F3:3E:FA:9A | 
| mozillacert122.pem |  Jun 18, 2018 | 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68 | 
| mozillacert56.pem |  Jun 18, 2018 | F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2 | 
| equifaxsecureebusinessca1 |  Apr 21, 2018 | AE:E6:3D:70:E3:76:FB:C7:3A:EB:B0:A1:C1:D4:C4:7A:A7:40:B3:F4 | 
| camerfirmachambersignca |  Apr 21, 2018 | 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C | 
| mozillacert114.pem |  Jun 18, 2018 | 51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39 | 
| mozillacert48.pem |  Jun 18, 2018 | A0:A1:AB:90:C9:FC:84:7B:3B:12:61:E8:97:7D:5F:D3:22:61:D3:CC | 
| pscprocert |  Jun 18, 2018 | 70:C1:8D:74:B4:28:81:0A:E4:FD:A5:75:D7:01:9F:99:B0:3D:50:74 | 
| mozillacert106.pem |  Jun 18, 2018 | E7:A1:90:29:D3:D5:52:DC:0D:0F:C6:92:D3:EA:88:0D:15:2E:1A:6B | 
| mozillacert1.pem |  Jun 18, 2018 | 23:E5:94:94:51:95:F2:41:48:03:B4:D5:64:D2:A3:A3:F5:D8:8B:8C | 
| eecertificationcentrerootca |  Jun 18, 2018 | C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7 | 
| digicertglobalrootca |  Jun 18, 2018 | A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36 | 
| thawteprimaryrootcag3 |  Jun 18, 2018 | F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2 | 
| thawteprimaryrootcag2 |  Jun 18, 2018 | AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12 | 
| entrustrootcertificationauthorityec1 |  Jun 18, 2018 | 20:D8:06:40:DF:9B:25:F5:12:25:3A:11:EA:F7:59:8A:EB:14:B5:47 | 
| valicertclass2ca |  Apr 21, 2018 | 31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6 | 
| globalchambersignroot2008 |  Jun 18, 2018 | 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C | 
| amazonrootca4 |  Jun 18, 2018 | F6:10:84:07:D6:F8:BB:67:98:0C:C2:E2:44:C2:EB:AE:1C:EF:63:BE | 
| gd-class2-root.pem |  Jun 18, 2018 | 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4 | 
| amazonrootca3 |  Jun 18, 2018 | 0D:44:DD:8C:3C:8C:1A:1A:58:75:64:81:E9:0F:2E:2A:FF:B3:D2:6E | 
| amazonrootca2 |  Jun 18, 2018 | 5A:8C:EF:45:D7:A6:98:59:76:7A:8C:8B:44:96:B5:78:CF:47:4B:1A | 
| securitycommunicationrootca |  Jun 18, 2018 | 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7 | 
| amazonrootca1 |  Jun 18, 2018 | 8D:A7:F9:65:EC:5E:FC:37:91:0F:1C:6E:59:FD:C1:CC:6A:6E:DE:16 | 
| acraizfnmtrcm |  Jun 18, 2018 | EC:50:35:07:B2:15:C4:95:62:19:E2:A8:9A:5B:42:99:2C:4C:2C:20 | 
| quovadisrootca3g3 |  Jun 18, 2018 | 48:12:BD:92:3C:A8:C4:39:06:E7:30:6D:27:96:E6:A4:CF:22:2E:7D | 
| certplusrootcag2 |  Jun 18, 2018 | 4F:65:8E:1F:E9:06:D8:28:02:E9:54:47:41:C9:54:25:5D:69:CC:1A | 
| certplusrootcag1 |  Jun 18, 2018 | 22:FD:D0:B7:FD:A2:4E:0D:AC:49:2C:A0:AC:A6:7B:6A:1F:E3:F7:66 | 
| mozillacert71.pem |  Jun 18, 2018 | 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C | 
| mozillacert63.pem |  Jun 18, 2018 | 89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E | 
| mozillacert121.pem |  Jun 18, 2018 | CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D | 
| ttelesecglobalrootclass3ca |  Apr 21, 2018 | 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 | 
| mozillacert55.pem |  Jun 18, 2018 | AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12 | 
| mozillacert113.pem |  Jun 18, 2018 | 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31 | 
| baltimorecybertrustca |  Apr 21, 2018 | D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 | 
| mozillacert47.pem |  Jun 18, 2018 | 1B:4B:39:61:26:27:6B:64:91:A2:68:6D:D7:02:43:21:2D:1F:1D:96 | 
| mozillacert105.pem |  Jun 18, 2018 | 77:47:4F:C6:30:E4:0F:4C:47:64:3F:84:BA:B8:C6:95:4A:8A:41:EC | 
| mozillacert39.pem |  Jun 18, 2018 | AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E | 
| usertrustecccertificationauthority |  Jun 18, 2018 | D1:CB:CA:5D:B2:D5:2A:7F:69:3B:67:4D:E5:F0:5A:1D:0C:95:7D:F0 | 
| mozillacert0.pem |  Jun 18, 2018 | 97:81:79:50:D8:1C:96:70:CC:34:D8:09:CF:79:44:31:36:7E:F4:74 | 
| securitycommunicationevrootca1 |  Jun 18, 2018 | FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D | 
| verisignc3g5.pem |  Jun 18, 2018 | 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 | 
| globalsignr3ca |  Apr 21, 2018 | D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD | 
| trustcoreca1 |  Jun 18, 2018 | 58:D1:DF:95:95:67:6B:63:C0:F0:5B:1C:17:4D:8B:84:0B:C8:78:BD | 
| equifaxsecureglobalebusinessca1 |  Apr 21, 2018 | 3A:74:CB:7A:47:DB:70:DE:89:1F:24:35:98:64:B8:2D:82:BD:1A:36 | 
| geotrustuniversalca |  Jun 18, 2018 | E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79 | 
| affirmtrustpremiumca |  Apr 21, 2018 | D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27 | 
| staatdernederlandenrootcag3 |  Jun 18, 2018 | D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC | 
| staatdernederlandenrootcag2 |  Jun 18, 2018 | 59:AF:82:79:91:86:C7:B4:75:07:CB:CF:03:57:46:EB:04:DD:B7:16 | 
| mozillacert70.pem |  Jun 18, 2018 | 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C | 
| secomevrootca1 |  Apr 21, 2018 | FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D | 
| geotrustglobalca |  Jun 18, 2018 | DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12 | 
| mozillacert62.pem |  Jun 18, 2018 | A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B | 
| mozillacert120.pem |  Jun 18, 2018 | DA:40:18:8B:91:89:A3:ED:EE:AE:DA:97:FE:2F:9D:F5:B7:D1:8A:41 | 
| mozillacert54.pem |  Jun 18, 2018 | 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD | 
| mozillacert112.pem |  Jun 18, 2018 | 43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37 | 
| mozillacert46.pem |  Jun 18, 2018 | 40:9D:4B:D9:17:B5:5C:27:B6:9B:64:CB:98:22:44:0D:CD:09:B8:89 | 
| swisssigngoldcag2 |  Jun 18, 2018 | D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61 | 
| mozillacert104.pem |  Jun 18, 2018 | 4F:99:AA:93:FB:2B:D1:37:26:A1:99:4A:CE:7F:F0:05:F2:93:5D:1E | 
| mozillacert38.pem |  Jun 18, 2018 | CB:A1:C5:F8:B0:E3:5E:B8:B9:45:12:D3:F9:34:A2:E9:06:10:D3:36 | 
| certplusclass3pprimaryca |  Apr 21, 2018 | 21:6B:2A:29:E6:2A:00:CE:82:01:46:D8:24:41:41:B9:25:11:B2:79 | 
| entrustrootcertificationauthorityg2 |  Jun 18, 2018 | 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4 | 
| godaddyrootg2ca |  Apr 21, 2018 | 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B | 
| cfcaevroot |  Jun 18, 2018 | E2:B8:29:4B:55:84:AB:6B:58:C2:90:46:6C:AC:3F:B8:39:8F:84:83 | 
| verisignc3g4.pem |  Jun 18, 2018 | 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A | 
| geotrustuniversalca2 |  Jun 18, 2018 | 37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79 | 
| starfieldservicesrootg2ca |  Apr 21, 2018 | 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F | 
| digicerthighassuranceevrootca |  Jun 18, 2018 | 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25 | 
| entrustnetpremium2048secureserverca |  Jun 18, 2018 | 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31 | 
| camerfirmaglobalchambersignroot |  Jun 18, 2018 | 33:9B:6B:14:50:24:9B:55:7A:01:87:72:84:D9:E0:2F:C3:D2:D8:E9 | 
| verisignclass3g3ca |  Apr 21, 2018 | 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 | 
| godaddyclass2ca |  Jun 18, 2018 | 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4 | 
| mozillacert61.pem |  Jun 18, 2018 | E0:B4:32:2E:B2:F6:A5:68:B6:54:53:84:48:18:4A:50:36:87:43:84 | 
| mozillacert53.pem |  Jun 18, 2018 | 7F:8A:B0:CF:D0:51:87:6A:66:F3:36:0F:47:C8:8D:8C:D3:35:FC:74 | 
| atostrustedroot2011 |  Jun 18, 2018 | 2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21 | 
| mozillacert111.pem |  Jun 18, 2018 | 9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65 | 
| staatdernederlandenevrootca |  Jun 18, 2018 | 76:E2:7E:C1:4F:DB:82:C1:C0:A6:75:B5:05:BE:3D:29:B4:ED:DB:BB | 
| mozillacert45.pem |  Jun 18, 2018 | 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0 | 
| mozillacert103.pem |  Jun 18, 2018 | 70:C1:8D:74:B4:28:81:0A:E4:FD:A5:75:D7:01:9F:99:B0:3D:50:74 | 
| mozillacert37.pem |  Jun 18, 2018 | B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97 | 
| mozillacert29.pem |  Jun 18, 2018 | 74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE | 
| izenpecom |  Jun 18, 2018 | 2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19 | 
| comodorsacertificationauthority |  Jun 18, 2018 | AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4 | 
| mozillacert99.pem |  Jun 18, 2018 | F1:7F:6F:B6:31:DC:99:E3:A3:C8:7F:FE:1C:F1:81:10:88:D9:60:33 | 
| mozillacert149.pem |  Jun 18, 2018 | 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1 | 
| utnuserfirstobjectca |  Apr 21, 2018 | E1:2D:FB:4B:41:D7:D9:C3:2B:30:51:4B:AC:1D:81:D8:38:5E:2D:46 | 
| verisignc3g3.pem |  Jun 18, 2018 | 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 | 
| dstrootcax3 |  Jun 18, 2018 | DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13 | 
| addtrustexternalroot |  Jun 18, 2018 | 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68 | 
| certumtrustednetworkca |  Jun 18, 2018 | 07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E | 
| affirmtrustpremiumecc |  Jun 18, 2018 | B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB | 
| starfieldclass2ca |  Jun 18, 2018 | AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A | 
| actalisauthenticationrootca |  Jun 18, 2018 | F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC | 
| verisignclass2g3ca |  Apr 21, 2018 | 61:EF:43:D7:7F:CA:D4:61:51:BC:98:E0:C3:59:12:AF:9F:EB:63:11 | 
| isrgrootx1 |  Jun 18, 2018 | CA:BD:2A:79:A1:07:6A:31:F2:1D:25:36:35:CB:03:9D:43:29:A5:E8 | 
| godaddyrootcertificateauthorityg2 |  Jun 18, 2018 | 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B | 
| mozillacert60.pem |  Jun 18, 2018 | 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3 | 
| chunghwaepkirootca |  Apr 21, 2018 | 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0 | 
| mozillacert52.pem |  Jun 18, 2018 | 8B:AF:4C:9B:1D:F0:2A:92:F7:DA:12:8E:B9:1B:AC:F4:98:60:4B:6F | 
| microseceszignorootca2009 |  Jun 18, 2018 | 89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E | 
| securesignrootca11 |  Jun 18, 2018 | 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3 | 
| mozillacert110.pem |  Jun 18, 2018 | 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17 | 
| mozillacert44.pem |  Jun 18, 2018 | 5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6 | 
| mozillacert102.pem |  Jun 18, 2018 | 96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83 | 
| mozillacert36.pem |  Jun 18, 2018 | 23:88:C9:D3:71:CC:9E:96:3D:FF:7D:3C:A7:CE:FC:D6:25:EC:19:0D | 
| mozillacert28.pem |  Jun 18, 2018 | 66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B | 
| baltimorecybertrustroot |  Jun 18, 2018 | D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 | 
| amzninternalrootca |  Dec 12, 2008 | A7:B7:F6:15:8A:FF:1E:C8:85:13:38:BC:93:EB:A2:AB:A4:09:EF:06 | 
| mozillacert98.pem |  Jun 18, 2018 | C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7 | 
| mozillacert148.pem |  Jun 18, 2018 | 04:83:ED:33:99:AC:36:08:05:87:22:ED:BC:5E:46:00:E3:BE:F9:D7 | 
| verisignc3g2.pem |  Jun 18, 2018 | 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F | 
| quovadisrootca2g3 |  Jun 18, 2018 | 09:3C:61:F3:8B:8B:DC:7D:55:DF:75:38:02:05:00:E1:25:F5:C8:36 | 
| geotrustprimarycertificationauthority |  Jun 18, 2018 | 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96 | 
| opentrustrootcag3 |  Jun 18, 2018 | 6E:26:64:F3:56:BF:34:55:BF:D1:93:3F:7C:01:DE:D8:13:DA:8A:A6 | 
| opentrustrootcag2 |  Jun 18, 2018 | 79:5F:88:60:C5:AB:7C:3D:92:E6:CB:F4:8D:E1:45:CD:11:EF:60:0B | 
| opentrustrootcag1 |  Jun 18, 2018 | 79:91:E8:34:F7:E2:EE:DD:08:95:01:52:E9:55:2D:14:E9:58:D5:7E | 
| verisignclass3ca |  Apr 21, 2018 | A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B | 
| globalsignca |  Apr 21, 2018 | B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C | 
| ttelesecglobalrootclass2ca |  Apr 21, 2018 | 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9 | 
| verisignclass1g3ca |  Apr 21, 2018 | 20:42:85:DC:F7:EB:76:41:95:57:8E:13:6B:D4:B7:D1:E9:8E:46:A5 | 
| verisignuniversalrootca |  Apr 21, 2018 | 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 | 
| soneraclass2ca |  Apr 21, 2018 | 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27 | 
| starfieldservicesrootcertificateauthorityg2 |  Jun 18, 2018 | 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F | 
| mozillacert51.pem |  Jun 18, 2018 | FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B | 
| mozillacert43.pem |  Jun 18, 2018 | F9:CD:0E:2C:DA:76:24:C1:8F:BD:F0:F0:AB:B6:45:B8:F7:FE:D5:7A | 
| mozillacert101.pem |  Jun 18, 2018 | 99:A6:9B:E6:1A:FE:88:6B:4D:2B:82:00:7C:B8:54:FC:31:7E:15:39 | 
| mozillacert35.pem |  Jun 18, 2018 | 2A:C8:D5:8B:57:CE:BF:2F:49:AF:F2:FC:76:8F:51:14:62:90:7A:41 | 
| globalsignr2ca |  Apr 21, 2018 | 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE | 
| mozillacert27.pem |  Jun 18, 2018 | 3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B | 
| affirmtrustpremium |  Jun 18, 2018 | D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27 | 
| mozillacert19.pem |  Jun 18, 2018 | B4:35:D4:E1:11:9D:1C:66:90:A7:49:EB:B3:94:BD:63:7B:A7:82:B7 | 
| mozillacert97.pem |  Jun 18, 2018 | 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F | 
| netlockaranyclassgoldfotanusitvany |  Jun 18, 2018 | 06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91 | 
| mozillacert89.pem |  Jun 18, 2018 | C8:EC:8C:87:92:69:CB:4B:AB:39:E9:8D:7E:57:67:F3:14:95:73:9D | 
| verisignroot.pem |  Jun 18, 2018 | 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 | 
| mozillacert147.pem |  Jun 18, 2018 | 58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4 | 
| aolrootca2 |  Apr 21, 2018 | 85:B5:FF:67:9B:0C:79:96:1F:C8:6E:44:22:00:46:13:DB:17:92:84 | 
| cia-crt-g3-01-ca |  Nov 23, 2016 | 2B:EE:2C:BA:A3:1D:B5:FE:60:40:41:95:08:ED:46:82:39:4D:ED:E2 | 
| aolrootca1 |  Apr 21, 2018 | 39:21:C1:15:C1:5D:0E:CA:5C:CB:5B:C4:F0:7D:21:D8:05:0B:56:6A | 
| verisignc3g1.pem |  Jun 18, 2018 | A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B | 
| mozillacert139.pem |  Jun 18, 2018 | DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9 | 
| soneraclass2rootca |  Jun 18, 2018 | 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27 | 
| swisssignsilverg2ca |  Apr 21, 2018 | 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB | 
| thawteprimaryrootca |  Jun 18, 2018 | 91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81 | 
| gdcatrustauthr5root |  Jun 18, 2018 | 0F:36:38:5B:81:1A:25:C3:9B:31:4E:83:CA:E9:34:66:70:CC:74:B4 | 
| trustcenterclass4caii |  Apr 21, 2018 | A6:9A:91:FD:05:7F:13:6A:42:63:0B:B1:76:0D:2D:51:12:0C:16:50 | 
| usertrustrsacertificationauthority |  Jun 18, 2018 | 2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E | 
| digicertassuredidrootg3 |  Jun 18, 2018 | F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89 | 
| digicertassuredidrootg2 |  Jun 18, 2018 | A1:4B:48:D9:43:EE:0A:0E:40:90:4F:3C:E0:A4:C0:91:93:51:5D:3F | 
| mozillacert50.pem |  Jun 18, 2018 | 8C:96:BA:EB:DD:2B:07:07:48:EE:30:32:66:A0:F3:98:6E:7C:AE:58 | 
| mozillacert42.pem |  Jun 18, 2018 | 85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF | 
| mozillacert100.pem |  Jun 18, 2018 | 58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0 | 
| mozillacert34.pem |  Jun 18, 2018 | 59:22:A1:E1:5A:EA:16:35:21:F8:98:39:6A:46:46:B0:44:1B:0F:A9 | 
| affirmtrustcommercialca |  Apr 21, 2018 | F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7 | 
| mozillacert26.pem |  Jun 18, 2018 | 87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11 | 
| globalsigneccrootcar5 |  Jun 18, 2018 | 1F:24:C6:30:CD:A4:18:EF:20:69:FF:AD:4F:DD:5F:46:3A:1B:69:AA | 
| globalsigneccrootcar4 |  Jun 18, 2018 | 69:69:56:2E:40:80:F4:24:A1:E7:19:9F:14:BA:F3:EE:58:AB:6A:BB | 
| buypassclass3rootca |  Jun 18, 2018 | DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57 | 
| mozillacert18.pem |  Jun 18, 2018 | 79:98:A3:08:E1:4D:65:85:E6:C2:1E:15:3A:71:9F:BA:5A:D3:4A:D9 | 
| mozillacert96.pem |  Jun 18, 2018 | 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 | 
| verisignc2g6.pem |  Jun 18, 2018 | 40:B3:31:A0:E9:BF:E8:55:BC:39:93:CA:70:4F:4E:C2:51:D4:1D:8F | 
| secomvalicertclass1ca |  Apr 21, 2018 | E5:DF:74:3C:B6:01:C4:9B:98:43:DC:AB:8C:E8:6A:81:10:9F:E4:8E | 
| mozillacert88.pem |  Jun 18, 2018 | FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D | 
| accvraiz1 |  Jun 18, 2018 | 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17 | 
| mozillacert146.pem |  Jun 18, 2018 | 21:FC:BD:8E:7F:6C:AF:05:1B:D1:B3:43:EC:A8:E7:61:47:F2:0F:8A | 
| mozillacert138.pem |  Jun 18, 2018 | E1:9F:E3:0E:8B:84:60:9E:80:9B:17:0D:72:A8:C5:BA:6E:14:09:BD | 
| verisignclass3g2ca |  Apr 21, 2018 | 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F | 
| dtrustrootclass3ca2ev2009 |  Jun 18, 2018 | 96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83 | 
| xrampglobalca |  Apr 21, 2018 | B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6 | 
| mozillacert9.pem |  Jun 18, 2018 | F4:8B:11:BF:DE:AB:BE:94:54:20:71:E6:41:DE:6B:BE:88:2B:40:B9 | 
| verisignuniversalrootcertificationauthority |  Jun 18, 2018 | 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 | 
| tubitakkamusmsslkoksertifikasisurum1 |  Jun 18, 2018 | 31:43:64:9B:EC:CE:27:EC:ED:3A:3F:0B:8F:0D:E4:E8:91:DD:EE:CA | 
| mozillacert41.pem |  Jun 18, 2018 | 6B:2F:34:AD:89:58:BE:62:FD:B0:6B:5C:CE:BB:9D:D9:4F:4E:39:F3 | 
| mozillacert33.pem |  Jun 18, 2018 | FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D | 
| mozillacert25.pem |  Jun 18, 2018 | 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 | 
| mozillacert17.pem |  Jun 18, 2018 | 40:54:DA:6F:1C:3F:40:74:AC:ED:0F:EC:CD:DB:79:D1:53:FB:90:1D | 
| mozillacert95.pem |  Jun 18, 2018 | DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57 | 
| affirmtrustpremiumeccca |  Apr 21, 2018 | B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB | 
| mozillacert87.pem |  Jun 18, 2018 | 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74 | 
| mozillacert145.pem |  Jun 18, 2018 | 10:1D:FA:3F:D5:0B:CB:BB:9B:B5:60:0C:19:55:A4:1A:F4:73:3A:04 | 
| mozillacert79.pem |  Jun 18, 2018 | D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27 | 
| mozillacert137.pem |  Jun 18, 2018 | 4A:65:D5:F4:1D:EF:39:B8:B8:90:4A:4A:D3:64:81:33:CF:C7:A1:D1 | 
| digicertassuredidrootca |  Jun 18, 2018 | 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43 | 
| addtrustqualifiedca |  Apr 21, 2018 | 4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E:C5:4D:8B:CF | 
| mozillacert129.pem |  Jun 18, 2018 | E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79 | 
| verisignclass2g2ca |  Apr 21, 2018 | B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9D | 
| baltimorecodesigningca |  Apr 21, 2018 | 30:46:D8:C8:88:FF:69:30:C3:4A:FC:CD:49:27:08:7C:60:56:7B:0D | 
| luxtrustglobalroot2 |  Jun 18, 2018 | 1E:0E:56:19:0A:D1:8B:25:98:B2:04:44:FF:66:8A:04:17:99:5F:3F | 
| visaecommerceroot |  Jun 18, 2018 | 70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62 | 
| oistewisekeyglobalrootgbca |  Jun 18, 2018 | 0F:F9:40:76:18:D3:D7:6A:4B:98:F0:A8:35:9E:0C:FD:27:AC:CC:ED | 
| mozillacert8.pem |  Jun 18, 2018 | 3E:2B:F7:F2:03:1B:96:F3:8C:E6:C4:D8:A8:5D:3E:2D:58:47:6A:0F | 
| comodocertificationauthority |  Jun 18, 2018 | 66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B | 
| cia-crt-g3-02-ca |  Nov 23, 2016 | 96:4A:BB:A7:BD:DA:FC:97:34:C0:0A:2D:F0:05:98:F7:E6:C6:6F:09 | 
| verisignc1g6.pem |  Jun 18, 2018 | 51:7F:61:1E:29:91:6B:53:82:FB:72:E7:44:D9:8D:C3:CC:53:6D:64 | 
| trustcenterclass2caii |  Apr 21, 2018 | AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E | 
| quovadisrootca1g3 |  Jun 18, 2018 | 1B:8E:EA:57:96:29:1A:C9:39:EA:B8:0A:81:1A:73:73:C0:93:79:67 | 
| mozillacert40.pem |  Jun 18, 2018 | 80:25:EF:F4:6E:70:C8:D4:72:24:65:84:FE:40:3B:8A:8D:6A:DB:F5 | 
| cadisigrootr2 |  Jun 18, 2018 | B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71 | 
| cadisigrootr1 |  Jun 18, 2018 | 8E:1C:74:F8:A6:20:B9:E5:8A:F4:61:FA:EC:2B:47:56:51:1A:52:C6 | 
| mozillacert32.pem |  Jun 18, 2018 | 60:D6:89:74:B5:C2:65:9E:8A:0F:C1:88:7C:88:D2:46:69:1B:18:2C | 
| utndatacorpsgcca |  Apr 21, 2018 | 58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4 | 
| mozillacert24.pem |  Jun 18, 2018 | 59:AF:82:79:91:86:C7:B4:75:07:CB:CF:03:57:46:EB:04:DD:B7:16 | 
| addtrustclass1ca |  Apr 21, 2018 | CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D | 
| mozillacert16.pem |  Jun 18, 2018 | DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13 | 
| affirmtrustnetworkingca |  Apr 21, 2018 | 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F | 
| mozillacert94.pem |  Jun 18, 2018 | 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99 | 
| mozillacert86.pem |  Jun 18, 2018 | 74:2C:31:92:E6:07:E4:24:EB:45:49:54:2B:E1:BB:C5:3E:61:74:E2 | 
| mozillacert144.pem |  Jun 18, 2018 | 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27 | 
| mozillacert78.pem |  Jun 18, 2018 | 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F | 
| mozillacert136.pem |  Jun 18, 2018 | D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 | 
| mozillacert128.pem |  Jun 18, 2018 | A9:E9:78:08:14:37:58:88:F2:05:19:B0:6D:2B:0D:2B:60:16:90:7D | 
| verisignclass1g2ca |  Apr 21, 2018 | 27:3E:E1:24:57:FD:C4:F9:0C:55:E8:2B:56:16:7F:62:F5:32:E5:47 | 
| hellenicacademicandresearchinstitutionsrootca2015 |  Jun 18, 2018 | 01:0C:06:95:A6:98:19:14:FF:BF:5F:C6:B0:B6:95:EA:29:E9:12:A6 | 
| soneraclass1ca |  Apr 21, 2018 | 07:47:22:01:99:CE:74:B9:7C:B0:3D:79:B2:64:A2:C8:55:E9:33:FF | 
| hellenicacademicandresearchinstitutionsrootca2011 |  Jun 18, 2018 | FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D | 
| certumtrustednetworkca2 |  Jun 18, 2018 | D3:DD:48:3E:2B:BF:4C:05:E8:AF:10:F5:FA:76:26:CF:D3:DC:30:92 | 
| equifaxsecureca |  Apr 21, 2018 | D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A | 
| thawteserverca |  Apr 21, 2018 | 9F:AD:91:A6:CE:6A:C6:C5:00:47:C4:4E:C9:D4:A5:0D:92:D8:49:79 | 
| mozillacert7.pem |  Jun 18, 2018 | AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A | 
| affirmtrustnetworking |  Jun 18, 2018 | 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F | 
| deprecateditsecca |  Jan 27, 2012 | 12:12:0B:03:0E:15:14:54:F4:DD:B3:F5:DE:13:6E:83:5A:29:72:9D | 
| globalsignrootcar3 |  Jun 18, 2018 | D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD | 
| globalsignrootcar2 |  Jun 18, 2018 | 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE | 
| quovadisrootca |  Jun 18, 2018 | DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9 | 
| mozillacert31.pem |  Jun 18, 2018 | 9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11 | 
| entrustrootcertificationauthority |  Jun 18, 2018 | B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 | 
| mozillacert23.pem |  Jun 18, 2018 | 91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81 | 
| mozillacert15.pem |  Jun 18, 2018 | 74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB | 
| verisignc2g3.pem |  Jun 18, 2018 | 61:EF:43:D7:7F:CA:D4:61:51:BC:98:E0:C3:59:12:AF:9F:EB:63:11 | 
| mozillacert93.pem |  Jun 18, 2018 | 31:F1:FD:68:22:63:20:EE:C6:3B:3F:9D:EA:4A:3E:53:7C:7C:39:17 | 
| mozillacert151.pem |  Jun 18, 2018 | AC:ED:5F:65:53:FD:25:CE:01:5F:1F:7A:48:3B:6A:74:9F:61:78:C6 | 
| mozillacert85.pem |  Jun 18, 2018 | CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48 | 
| certplusclass2primaryca |  Jun 18, 2018 | 74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB | 
| mozillacert143.pem |  Jun 18, 2018 | 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7 | 
| mozillacert77.pem |  Jun 18, 2018 | 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 | 
| mozillacert135.pem |  Jun 18, 2018 | 62:52:DC:40:F7:11:43:A2:2F:DE:9E:F7:34:8E:06:42:51:B1:81:18 | 
| mozillacert69.pem |  Jun 18, 2018 | 2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19 | 
| mozillacert127.pem |  Jun 18, 2018 | DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12 | 
| mozillacert119.pem |  Jun 18, 2018 | 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE | 
| geotrustprimarycag3 |  Apr 21, 2018 | 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD | 
| identrustpublicsectorrootca1 |  Jun 18, 2018 | BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD | 
| geotrustprimarycag2 |  Apr 21, 2018 | 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0 | 
| trustcorrootcertca2 |  Jun 18, 2018 | B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0 | 
| mozillacert6.pem |  Jun 18, 2018 | 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4 | 
| trustcorrootcertca1 |  Jun 18, 2018 | FF:BD:CD:E7:82:C8:43:5E:3C:6F:26:86:5C:CA:A8:3A:45:5B:C3:0A | 
| networksolutionscertificateauthority |  Jun 18, 2018 | 74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE | 
| twcarootcertificationauthority |  Jun 18, 2018 | CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48 | 
| addtrustexternalca |  Apr 21, 2018 | 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68 | 
| verisignclass3g5ca |  Apr 21, 2018 | 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 | 
| autoridaddecertificacionfirmaprofesionalcifa62634068 |  Jun 18, 2018 | AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA | 
| hellenicacademicandresearchinstitutionseccrootca2015 |  Jun 18, 2018 | 9F:F1:71:8D:92:D5:9A:F3:7D:74:97:B4:BC:6F:84:68:0B:BA:B6:66 | 
| verisigntsaca |  Apr 21, 2018 | 20:CE:B1:F0:F5:1C:0E:19:A9:F3:8D:B1:AA:8E:03:8C:AA:7A:C7:01 | 
| utnuserfirsthardwareca |  Apr 21, 2018 | 04:83:ED:33:99:AC:36:08:05:87:22:ED:BC:5E:46:00:E3:BE:F9:D7 | 
| identrustcommercialrootca1 |  Jun 18, 2018 | DF:71:7E:AA:4A:D9:4E:C9:55:84:99:60:2D:48:DE:5F:BC:F0:3A:25 | 
| dtrustrootclass3ca22009 |  Jun 18, 2018 | 58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0 | 
| epkirootcertificationauthority |  Jun 18, 2018 | 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0 | 
| mozillacert30.pem |  Jun 18, 2018 | E7:B4:F6:9D:61:EC:90:69:DB:7E:90:A7:40:1A:3C:F4:7D:4F:E8:EE | 
| teliasonerarootcav1 |  Jun 18, 2018 | 43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37 | 
| buypassclass3ca |  Apr 21, 2018 | DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57 | 
| mozillacert22.pem |  Jun 18, 2018 | 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96 | 
| mozillacert14.pem |  Jun 18, 2018 | 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25 | 
| verisignc2g2.pem |  Jun 18, 2018 | B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9D | 
| certumca |  Apr 21, 2018 | 62:52:DC:40:F7:11:43:A2:2F:DE:9E:F7:34:8E:06:42:51:B1:81:18 | 
| mozillacert92.pem |  Jun 18, 2018 | A3:F1:33:3F:E2:42:BF:CF:C5:D1:4E:8F:39:42:98:40:68:10:D1:A0 | 
| mozillacert150.pem |  Jun 18, 2018 | 33:9B:6B:14:50:24:9B:55:7A:01:87:72:84:D9:E0:2F:C3:D2:D8:E9 | 
| mozillacert84.pem |  Jun 18, 2018 | D3:C0:63:F2:19:ED:07:3E:34:AD:5D:75:0B:32:76:29:FF:D5:9A:F2 | 
| ttelesecglobalrootclass3 |  Jun 18, 2018 | 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1 | 
| globalsignrootca |  Jun 18, 2018 | B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C | 
| ttelesecglobalrootclass2 |  Jun 18, 2018 | 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9 | 
| mozillacert142.pem |  Jun 18, 2018 | 1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85 | 
| mozillacert76.pem |  Jun 18, 2018 | F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7 | 
| mozillacert134.pem |  Jun 18, 2018 | 70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62 | 
| mozillacert68.pem |  Jun 18, 2018 | AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA | 
| etugracertificationauthority |  Jun 18, 2018 | 51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39 | 
| mozillacert126.pem |  Jun 18, 2018 | 25:01:90:19:CF:FB:D9:99:1C:B7:68:25:74:8D:94:5F:30:93:95:42 | 
| keynectisrootca |  Apr 21, 2018 | 9C:61:5C:4D:4D:85:10:3A:53:26:C2:4D:BA:EA:E4:A2:D2:D5:CC:97 | 
| mozillacert118.pem |  Jun 18, 2018 | 7E:78:4A:10:1C:82:65:CC:2D:E1:F1:6D:47:B4:40:CA:D9:0A:19:45 | 
| quovadisrootca3 |  Jun 18, 2018 | 1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85 | 
| quovadisrootca2 |  Jun 18, 2018 | CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7 | 
| mozillacert5.pem |  Jun 18, 2018 | B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6 | 
| verisignc1g3.pem |  Jun 18, 2018 | 20:42:85:DC:F7:EB:76:41:95:57:8E:13:6B:D4:B7:D1:E9:8E:46:A5 | 
| cybertrustglobalroot |  Jun 18, 2018 | 5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6 | 
| amzninternalinfoseccag3 |  Feb 27, 2015 | B9:B1:CA:38:F7:BF:9C:D2:D4:95:E7:B6:5E:75:32:9B:A8:78:2E:F6 | 
| starfieldrootcertificateauthorityg2 |  Jun 18, 2018 | B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E | 
| entrust2048ca |  Apr 21, 2018 | 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31 | 
| swisssignsilvercag2 |  Jun 18, 2018 | 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB | 
| affirmtrustcommercial |  Jun 18, 2018 | F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7 | 
| certinomisrootca |  Jun 18, 2018 | 9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8 | 
| xrampglobalcaroot |  Jun 18, 2018 | B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6 | 
| secureglobalca |  Jun 18, 2018 | 3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B | 
| swisssigngoldg2ca |  Apr 21, 2018 | D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61 | 
| mozillacert21.pem |  Jun 18, 2018 | 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB | 
| mozillacert13.pem |  Jun 18, 2018 | 06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91 | 
| verisignc2g1.pem |  Jun 18, 2018 | 67:82:AA:E0:ED:EE:E2:1A:58:39:D3:C0:CD:14:68:0A:4F:60:14:2A | 
| mozillacert91.pem |  Jun 18, 2018 | 3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04 | 
| oistewisekeyglobalrootgaca |  Jun 18, 2018 | 59:22:A1:E1:5A:EA:16:35:21:F8:98:39:6A:46:46:B0:44:1B:0F:A9 | 
| mozillacert83.pem |  Jun 18, 2018 | A0:73:E5:C5:BD:43:61:0D:86:4C:21:13:0A:85:58:57:CC:9C:EA:46 | 
| entrustevca |  Apr 21, 2018 | B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 | 
| mozillacert141.pem |  Jun 18, 2018 | 31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6 | 
| mozillacert75.pem |  Jun 18, 2018 | D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A | 
| mozillacert133.pem |  Jun 18, 2018 | 85:B5:FF:67:9B:0C:79:96:1F:C8:6E:44:22:00:46:13:DB:17:92:84 | 
| mozillacert67.pem |  Jun 18, 2018 | D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD | 
| mozillacert125.pem |  Jun 18, 2018 | B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9 | 
| mozillacert59.pem |  Jun 18, 2018 | 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54 | 
| thawtepremiumserverca |  Apr 21, 2018 | E0:AB:05:94:20:72:54:93:05:60:62:02:36:70:F7:CD:2E:FC:66:66 | 
| mozillacert117.pem |  Jun 18, 2018 | D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74 | 
| utnuserfirstclientauthemailca |  Apr 21, 2018 | B1:72:B1:A5:6D:95:F9:1F:E5:02:87:E1:4D:37:EA:6A:44:63:76:8A | 
| entrustrootcag2 |  Apr 21, 2018 | 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4 | 
| mozillacert109.pem |  Jun 18, 2018 | B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71 | 
| digicerttrustedrootg4 |  Jun 18, 2018 | DD:FB:16:CD:49:31:C9:73:A2:03:7D:3F:C8:3A:4D:7D:77:5D:05:E4 | 
| gdroot-g2.pem |  Jun 18, 2018 | 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B | 
| comodoaaaservicesroot |  Jun 18, 2018 | D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49 | 
| mozillacert4.pem |  Jun 18, 2018 | E3:92:51:2F:0A:CF:F5:05:DF:F6:DE:06:7F:75:37:E1:65:EA:57:4B | 
| verisignclass3publicprimarycertificationauthorityg5 |  Jun 18, 2018 | 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5 | 
| chambersofcommerceroot2008 |  Jun 18, 2018 | 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C | 
| verisignclass3publicprimarycertificationauthorityg4 |  Jun 18, 2018 | 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A | 
| verisignclass3publicprimarycertificationauthorityg3 |  Jun 18, 2018 | 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6 | 
| thawtepersonalfreemailca |  Apr 21, 2018 | E6:18:83:AE:84:CA:C1:C1:CD:52:AD:E8:E9:25:2B:45:A6:4F:B7:E2 | 
| verisignc1g2.pem |  Jun 18, 2018 | 27:3E:E1:24:57:FD:C4:F9:0C:55:E8:2B:56:16:7F:62:F5:32:E5:47 | 
| gtecybertrustglobalca |  Apr 21, 2018 | 97:81:79:50:D8:1C:96:70:CC:34:D8:09:CF:79:44:31:36:7E:F4:74 | 
| trustcenteruniversalcai |  Apr 21, 2018 | 6B:2F:34:AD:89:58:BE:62:FD:B0:6B:5C:CE:BB:9D:D9:4F:4E:39:F3 | 
| camerfirmachamberscommerceca |  Apr 21, 2018 | 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1 | 
| verisignclass1ca |  Apr 21, 2018 | CE:6A:64:A3:09:E4:2F:BB:D9:85:1C:45:3E:64:09:EA:E8:7D:60:F1 | 

# AWS AppSync resolver mapping template changelog
<a name="resolver-mapping-template-changelog"></a>

**Note**  
We now primarily support the APPSYNC\$1JS runtime and its documentation. Please consider using the APPSYNC\$1JS runtime and its guides [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html).

Resolver and function mapping templates are versioned. The mapping template version, such as `2018-05-29`) dictates the following:
+ The expected shape of the data source request configuration provided by the request template
+ The execution behavior of the request mapping template and the response mapping template

Versions are represented using the YYYY-MM-DD format, a later date corresponds to a more recent version. This page lists the differences between the mapping template versions currently supported in AWS AppSync.

**Topics**
+ [Datasource Operation Availability Per Version Matrix](#aws-appsync-resolver-mapping-template-operation-availability-per-version)
+ [Changing the Version on a Unit Resolver Mapping Template](#changing-the-version-on-a-unit-resolver-mapping-template)
+ [Changing the Version on a Function](#changing-the-version-on-a-function)
+ [2018-05-29](#aws-appsync-resolver-mapping-template-version-2018-05-29)
+ [2017-02-28](#aws-appsync-resolver-mapping-template-version-2017-02-28)

## Datasource Operation Availability Per Version Matrix
<a name="aws-appsync-resolver-mapping-template-operation-availability-per-version"></a>


| Operation/Version Supported | 2017-02-28 | 2018-05-29 | 
| --- | --- | --- | 
|  AWS Lambda Invoke  |  Yes  |  Yes  | 
|  AWS Lambda BatchInvoke  |  Yes  |  Yes  | 
|  None Datasource  |  Yes  |  Yes  | 
|  Amazon OpenSearch GET  |  Yes  |  Yes  | 
|  Amazon OpenSearch POST  |  Yes  |  Yes  | 
|  Amazon OpenSearch PUT  |  Yes  |  Yes  | 
|  Amazon OpenSearch DELETE  |  Yes  |  Yes  | 
|  Amazon OpenSearch GET  |  Yes  |  Yes  | 
|  DynamoDB GetItem  |  Yes  |  Yes  | 
|  DynamoDB Scan  |  Yes  |  Yes  | 
|  DynamoDB Query  |  Yes  |  Yes  | 
|  DynamoDB DeleteItem  |  Yes  |  Yes  | 
|  DynamoDB PutItem  |  Yes  |  Yes  | 
|  DynamoDB BatchGetItem  |  No  |  Yes  | 
|  DynamoDB BatchPutItem  |  No  |  Yes  | 
|  DynamoDB BatchDeleteItem  |  No  |  Yes  | 
|  HTTP  |  No  |  Yes  | 
|  Amazon RDS  |  No  |  Yes  | 

 **Note**: Only **2018-05-29** version is currently supported in functions.

## Changing the Version on a Unit Resolver Mapping Template
<a name="changing-the-version-on-a-unit-resolver-mapping-template"></a>

For Unit resolvers, the version is specified as part of the body of the request mapping template. To update the version, simply update the `version` field to the new version.

For example, to update the version on the AWS Lambda template:

```
{
    "version": "2017-02-28",
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "arguments": $utils.toJson($context.arguments)
    }
}
```

You need to update the version field from `2017-02-28` to `2018-05-29` as follows:

```
{
    "version": "2018-05-29", ## Note the version
    "operation": "Invoke",
    "payload": {
        "field": "getPost",
        "arguments": $utils.toJson($context.arguments)
    }
}
```

## Changing the Version on a Function
<a name="changing-the-version-on-a-function"></a>

For functions, the version is specified as the `functionVersion` field on the function object. To update the version, simply update the `functionVersion`. *Note:* Currently, only `2018-05-29` is supported for function.

The following is an example of a CLI command to update an existing function version:

```
aws appsync update-function \
--api-id REPLACE_WITH_API_ID \
--function-id REPLACE_WITH_FUNCTION_ID \
--data-source-name "PostTable" \
--function-version "2018-05-29" \
--request-mapping-template "{...}" \
--response-mapping-template "\$util.toJson(\$ctx.result)"
```

 **Note:** It is recommended to omit the version field from the function request mapping template as it will not be honored. If you do specify a version inside a function request mapping template, the version value will be overridden by the value of the `functionVersion` field.

## 2018-05-29
<a name="aws-appsync-resolver-mapping-template-version-2018-05-29"></a>

### Behavior Change
<a name="behavior-change"></a>
+ If the datasource invocation result is `null`, the response mapping template is executed.
+ If the datasource invocation yields an error, it is now up to you to handle the error, the response mapping template evaluated result will **always** be placed inside the GraphQL response `data` block.

### Reasoning
<a name="reasoning"></a>
+ A `null` invocation result has meaning, and in some application use cases we might want to handle `null` results in a custom way. For example, an application might check if a record exists in an Amazon DynamoDB table to perform some authorization check. In this case, a `null` invocation result would mean the user might not be authorized. Executing the response mapping template now provides the ability to raise an unauthorized error. This behavior provides greater control to the API designer.

Given the following response mapping template:

```
$util.toJson($ctx.result)
```

Previously with `2017-02-28`, if `$ctx.result` came back null, the response mapping template was not executed. With `2018-05-29`, we can now handle this scenario. For example, we can choose to raise an authorization error as follows:

```
# throw an unauthorized error if the result is null
#if ( $util.isNull($ctx.result) )
    $util.unauthorized()
#end
$util.toJson($ctx.result)
```

 **Note:** Errors coming back from a data source are sometimes not fatal or even expected, that is why the response mapping template should be given the flexibility to handle the invocation error and decide whether to ignore it, re-raise it, or throw a different error.

Given the following response mapping template:

```
$util.toJson($ctx.result)
```

Previously, with `2017-02-28`, in case of an invocation error, the response mapping template was evaluated and the result was placed automatically in the `errors` block of the GraphQL response. With `2018-05-29`, we can now choose what to do with the error, re-raise it, raise a different error, or append the error while return data.

### Re-raise an Invocation Error
<a name="re-raise-an-invocation-error"></a>

In the following response template, we raise the same error that came back from the data source.

```
#if ( $ctx.error )
    $util.error($ctx.error.message, $ctx.error.type)
#end
$util.toJson($ctx.result)
```

In case of an invocation error (for example, `$ctx.error` is present) the response looks like the following:

```
{
    "data": {
        "getPost": null
    },
    "errors": [
        {
            "path": [
                "getPost"
            ],
            "errorType": "DynamoDB:ConditionalCheckFailedException",
            "message": "Conditional check failed exception...",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ]
        }
    ]
}
```

### Raise a Different Error
<a name="raise-a-different-error"></a>

In the following response template, we raise our own custom error after processing the error that came back from the data source.

```
#if ( $ctx.error )
    #if ( $ctx.error.type.equals("ConditionalCheckFailedException") )
        ## we choose here to change the type and message of the error for ConditionalCheckFailedExceptions
        $util.error("Error while updating the post, try again. Error: $ctx.error.message", "UpdateError")
    #else
        $util.error($ctx.error.message, $ctx.error.type)
    #end
#end
$util.toJson($ctx.result)
```

In case of an invocation error (for example, `$ctx.error` is present) the response looks like the following:

```
{
    "data": {
        "getPost": null
    },
    "errors": [
        {
            "path": [
                "getPost"
            ],
            "errorType": "UpdateError",
            "message": "Error while updating the post, try again. Error: Conditional check failed exception...",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ]
        }
    ]
}
```

### Append an Error to Return Data
<a name="append-an-error-to-return-data"></a>

In the following response template, we append the same error that came back from the data source while returning data back inside the response. This is also known as a partial response.

```
#if ( $ctx.error )
    $util.appendError($ctx.error.message, $ctx.error.type)
    #set($defaultPost = {id: "1", title: 'default post'})
    $util.toJson($defaultPost)
#else
    $util.toJson($ctx.result)
#end
```

In case of an invocation error (for example, `$ctx.error` is present) the response looks like the following:

```
{
    "data": {
        "getPost": {
            "id": "1",
            "title: "A post"
        }
    },
    "errors": [
        {
            "path": [
                "getPost"
            ],
            "errorType": "ConditionalCheckFailedException",
            "message": "Conditional check failed exception...",
            "locations": [
                {
                    "line": 5,
                    "column": 5
                }
            ]
        }
    ]
}
```

#### Migrating from *2017-02-28* to *2018-05-29*
<a name="migrating-from-2017-02-28-to-2018-05-29"></a>

Migrating from **2017-02-28** to **2018-05-29** is straightforward. Change the version field on the resolver request mapping template or on the function version object. However, note that **2018-05-29** execution behaves differently from **2017-02-28**, changes are outlined [here](#aws-appsync-resolver-mapping-template-version-2018-05-29).

#### Preserving the same execution behavior from *2017-02-28* to *2018-05-29*
<a name="preserving-the-same-execution-behavior-from-2017-02-28-to-2018-05-29"></a>

In some cases, it is possible to retain the same execution behavior as the **2017-02-28** version while executing a **2018-05-29** versioned template.

### Example: DynamoDB PutItem
<a name="example-dynamodb-putitem"></a>

Given the following **2017-02-28** DynamoDB PutItem request template:

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key": {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "attributeValues" : {
        "baz" : ... typed value
    },
    "condition" : {
       ...
    }
}
```

And the following response template:

```
$util.toJson($ctx.result)
```

Migrating to **2018-05-29** changes these templates as follows:

```
{
    "version" : "2018-05-29", ## Note the new 2018-05-29 version
    "operation" : "PutItem",
    "key": {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "attributeValues" : {
        "baz" : ... typed value
    },
    "condition" : {
       ...
    }
}
```

And changes the response template as follows:

```
## If there is a datasource invocation error, we choose to raise the same error
## the field data will be set to null.
#if($ctx.error)
  $util.error($ctx.error.message, $ctx.error.type, $ctx.result)
#end

## If the data source invocation is null, we return null.
#if($util.isNull($ctx.result))
  #return
#end

$util.toJson($ctx.result)
```

Now that it is your responsibility to handle errors, we chose to raise the same error using `$util.error()` that was returned from DynamoDB. You can adapt this snippet to convert your mapping template to **2018-05-29**, note that if your response template is different you will have to take account of the execution behavior changes.

### Example: DynamoDB GetItem
<a name="example-dynamodb-getitem"></a>

Given the following **2017-02-28** DynamoDB GetItem request template:

```
{
    "version" : "2017-02-28",
    "operation" : "GetItem",
    "key" : {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "consistentRead" : true
}
```

And the following response template:

```
## map table attribute postId to field Post.id
$util.qr($ctx.result.put("id", $ctx.result.get("postId")))

$util.toJson($ctx.result)
```

Migrating to **2018-05-29** changes these templates as follows:

```
{
    "version" : "2018-05-29", ## Note the new 2018-05-29 version
    "operation" : "GetItem",
    "key" : {
        "foo" : ... typed value,
        "bar" : ... typed value
    },
    "consistentRead" : true
}
```

And changes the response template as follows:

```
## If there is a datasource invocation error, we choose to raise the same error
#if($ctx.error)
  $util.error($ctx.error.message, $ctx.error.type)
#end

## If the data source invocation is null, we return null.
#if($util.isNull($ctx.result))
  #return
#end

## map table attribute postId to field Post.id
$util.qr($ctx.result.put("id", $ctx.result.get("postId")))

$util.toJson($ctx.result)
```

In the **2017-02-28** version, if the datasource invocation was `null`, meaning there is no item in the DynamoDB table that matches our key, the response mapping template would not execute. It might be fine for most of the cases, but if you expected the `$ctx.result` to not be `null`, you now have to handle that scenario.

## 2017-02-28
<a name="aws-appsync-resolver-mapping-template-version-2017-02-28"></a>

### Characteristics
<a name="characteristics"></a>
+ If the datasource invocation result is `null`, the response mapping template is **not** executed.
+ If the datasource invocation yields an error, the response mapping template is executed and the evaluated result is placed inside the GraphQL response `errors.data` block.