> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.bigcommerce.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.bigcommerce.com/_mcp/server.

# Upsert Custom Template Associations

PUT https://api.bigcommerce.com/stores/{store_hash}/v3/storefront/custom-template-associations
Content-Type: application/json

Upsert new custom template associations data across all storefronts. If an existing record is found for the combination of channel ID, entity ID, and type, the existing record will be overwritten with the new template.

Reference: https://docs.bigcommerce.com/developer/api-reference/rest/admin/content/custom-template-associations/upsert-custom-template-associations

## Authentication

- `X-Auth-Token` header (required) — ### OAuth scopes | UI Name | Permission | Parameter | |:--------|:-----------|:----------| | Themes |Read-only|`store_themes_read_only`| | Themes |Manage|`store_themes_manage`| ### Authentication header | Header | Argument | Description | |:-------|:---------|:------------| | `X-Auth-Token` | `access_token` | For more about API accounts that generate `access_token`s, see our [Guide to API Accounts](/developer/docs/overview/api-fundamentals/api-accounts#api-accounts). | ### Further reading For example requests and more information about authenticating BigCommerce APIs, see [Authentication and Example Requests](/developer/docs/overview/api-fundamentals/api-accounts#x-auth-token-header-example-requests). For more about BigCommerce OAuth scopes, see our [Guide to API Accounts](/developer/docs/overview/api-fundamentals/api-accounts#oauth-scopes). For a list of API status codes, see [API Status Codes](/developer/api-reference/rest/overview#rest-http-status-codes).

## Request

### Path parameters

- `store_hash` (string, required) — Permanent ID of the BigCommerce store.

### Headers

- `Accept` (string, required, default: application/json) — The [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) of the response body.

### Body (application/json)

This endpoint expects a list of CustomTemplateAssociationUpsert.

- `list of CustomTemplateAssociationUpsert`

## Response

### 200

Success response for batch upsert of custom template associations

## Errors

### 422 Unprocessable Entity Error

Error response for batch PUT of Custom template associations. Includes the errors for each reference ID.

- `errors` (DetailedErrors, optional)
- `instance` (string, optional)
- `status` (integer, optional) — The HTTP status code.
- `title` (string, optional) — The error title describing the particular error.
- `type` (string, optional)

## Types

### CustomTemplateAssociationUpsert

- `channel_id` (integer, required)
- `entity_type` (enum, required)
  - Allowed values: `product`, `category`, `brand`, `page`
- `entity_id` (integer, required)
- `file_name` (string, required)

### DetailedErrors

## Examples

**Request**

```json
[
  {
    "channel_id": 1,
    "entity_type": "brand",
    "entity_id": 123,
    "file_name": "custom-brand-1.html"
  },
  {
    "channel_id": 12345,
    "entity_type": "page",
    "entity_id": 123,
    "file_name": "custom-page.html"
  },
  {
    "channel_id": 67543,
    "entity_type": "product",
    "entity_id": 12,
    "file_name": "custom-product-1.html"
  }
]
```

**Response**

```json
{}
```

**SDK Code**

```python example-1
import requests

url = "https://api.bigcommerce.com/stores/store_hash/v3/storefront/custom-template-associations"

payload = [
    {
        "channel_id": 1,
        "entity_type": "brand",
        "entity_id": 123,
        "file_name": "custom-brand-1.html"
    },
    {
        "channel_id": 12345,
        "entity_type": "page",
        "entity_id": 123,
        "file_name": "custom-page.html"
    },
    {
        "channel_id": 67543,
        "entity_type": "product",
        "entity_id": 12,
        "file_name": "custom-product-1.html"
    }
]
headers = {
    "Accept": "application/json",
    "X-Auth-Token": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.put(url, json=payload, headers=headers)

print(response.json())
```

```javascript example-1
const url = 'https://api.bigcommerce.com/stores/store_hash/v3/storefront/custom-template-associations';
const options = {
  method: 'PUT',
  headers: {
    Accept: 'application/json',
    'X-Auth-Token': '<apiKey>',
    'Content-Type': 'application/json'
  },
  body: '[{"channel_id":1,"entity_type":"brand","entity_id":123,"file_name":"custom-brand-1.html"},{"channel_id":12345,"entity_type":"page","entity_id":123,"file_name":"custom-page.html"},{"channel_id":67543,"entity_type":"product","entity_id":12,"file_name":"custom-product-1.html"}]'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go example-1
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.bigcommerce.com/stores/store_hash/v3/storefront/custom-template-associations"

	payload := strings.NewReader("[\n  {\n    \"channel_id\": 1,\n    \"entity_type\": \"brand\",\n    \"entity_id\": 123,\n    \"file_name\": \"custom-brand-1.html\"\n  },\n  {\n    \"channel_id\": 12345,\n    \"entity_type\": \"page\",\n    \"entity_id\": 123,\n    \"file_name\": \"custom-page.html\"\n  },\n  {\n    \"channel_id\": 67543,\n    \"entity_type\": \"product\",\n    \"entity_id\": 12,\n    \"file_name\": \"custom-product-1.html\"\n  }\n]")

	req, _ := http.NewRequest("PUT", url, payload)

	req.Header.Add("Accept", "application/json")
	req.Header.Add("X-Auth-Token", "<apiKey>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby example-1
require 'uri'
require 'net/http'

url = URI("https://api.bigcommerce.com/stores/store_hash/v3/storefront/custom-template-associations")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)
request["Accept"] = 'application/json'
request["X-Auth-Token"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "[\n  {\n    \"channel_id\": 1,\n    \"entity_type\": \"brand\",\n    \"entity_id\": 123,\n    \"file_name\": \"custom-brand-1.html\"\n  },\n  {\n    \"channel_id\": 12345,\n    \"entity_type\": \"page\",\n    \"entity_id\": 123,\n    \"file_name\": \"custom-page.html\"\n  },\n  {\n    \"channel_id\": 67543,\n    \"entity_type\": \"product\",\n    \"entity_id\": 12,\n    \"file_name\": \"custom-product-1.html\"\n  }\n]"

response = http.request(request)
puts response.read_body
```

```java example-1
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.put("https://api.bigcommerce.com/stores/store_hash/v3/storefront/custom-template-associations")
  .header("Accept", "application/json")
  .header("X-Auth-Token", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("[\n  {\n    \"channel_id\": 1,\n    \"entity_type\": \"brand\",\n    \"entity_id\": 123,\n    \"file_name\": \"custom-brand-1.html\"\n  },\n  {\n    \"channel_id\": 12345,\n    \"entity_type\": \"page\",\n    \"entity_id\": 123,\n    \"file_name\": \"custom-page.html\"\n  },\n  {\n    \"channel_id\": 67543,\n    \"entity_type\": \"product\",\n    \"entity_id\": 12,\n    \"file_name\": \"custom-product-1.html\"\n  }\n]")
  .asString();
```

```php example-1
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PUT', 'https://api.bigcommerce.com/stores/store_hash/v3/storefront/custom-template-associations', [
  'body' => '[
  {
    "channel_id": 1,
    "entity_type": "brand",
    "entity_id": 123,
    "file_name": "custom-brand-1.html"
  },
  {
    "channel_id": 12345,
    "entity_type": "page",
    "entity_id": 123,
    "file_name": "custom-page.html"
  },
  {
    "channel_id": 67543,
    "entity_type": "product",
    "entity_id": 12,
    "file_name": "custom-product-1.html"
  }
]',
  'headers' => [
    'Accept' => 'application/json',
    'Content-Type' => 'application/json',
    'X-Auth-Token' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp example-1
using RestSharp;

var client = new RestClient("https://api.bigcommerce.com/stores/store_hash/v3/storefront/custom-template-associations");
var request = new RestRequest(Method.PUT);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-Auth-Token", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "[\n  {\n    \"channel_id\": 1,\n    \"entity_type\": \"brand\",\n    \"entity_id\": 123,\n    \"file_name\": \"custom-brand-1.html\"\n  },\n  {\n    \"channel_id\": 12345,\n    \"entity_type\": \"page\",\n    \"entity_id\": 123,\n    \"file_name\": \"custom-page.html\"\n  },\n  {\n    \"channel_id\": 67543,\n    \"entity_type\": \"product\",\n    \"entity_id\": 12,\n    \"file_name\": \"custom-product-1.html\"\n  }\n]", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift example-1
import Foundation

let headers = [
  "Accept": "application/json",
  "X-Auth-Token": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  [
    "channel_id": 1,
    "entity_type": "brand",
    "entity_id": 123,
    "file_name": "custom-brand-1.html"
  ],
  [
    "channel_id": 12345,
    "entity_type": "page",
    "entity_id": 123,
    "file_name": "custom-page.html"
  ],
  [
    "channel_id": 67543,
    "entity_type": "product",
    "entity_id": 12,
    "file_name": "custom-product-1.html"
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.bigcommerce.com/stores/store_hash/v3/storefront/custom-template-associations")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PUT"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```