> 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.

# Import Coupon Codes

POST https://api.bigcommerce.com/stores/{store_hash}/v3/promotions/{promotion_id}/import-codes
Content-Type: multipart/form-data

Uploads a CSV file of coupon codes to import into a bulk coupon promotion.

The request validates the whole file before it creates any codes. If the file passes, the import is queued, the codes are created in the background, and the response returns the task that tracks the import. To follow its progress, poll [Get Latest Promotion Task](/developer/api-reference/rest/admin/management/promotions/promotion-tasks/get-latest-promotion-task).

**CSV format**

The first line must be this header: `code,max_uses,max_uses_per_customer,valid_from,valid_until`. Every row after it must have all five columns. Blank lines are skipped.

| Column | Required | Description |
|:-------|:---------|:------------|
| `code` | Yes | The coupon code. 1 to 50 characters, using only letters, numbers, spaces, underscores, and hyphens. Cannot be `0`. |
| `max_uses` | No | The maximum number of times the code can be used, as a whole number from 0 to 2147483647. `0` means unlimited. When blank, the code uses the promotion's `max_uses`, or `0` if the promotion has none. |
| `max_uses_per_customer` | No | The maximum number of times one customer can use the code, as a whole number from 0 to 2147483647. `0` means unlimited. When blank, the value is `0`. |
| `valid_from` | No | The start of the code's redemption window, as an RFC 3339 date-time with a time zone, for example `2026-08-12T04:00:00+00:00`. Required when `valid_until` is set. When `valid_from` and `valid_until` are both blank, the code follows the promotion's schedule. |
| `valid_until` | No | The end of the code's redemption window, as an RFC 3339 date-time. Must be after `valid_from`. Required when `valid_from` is set and the promotion has an end date. |

A custom redemption window must fall within the promotion's start and end dates. Dates must be after `1970-01-01T00:00:00+00:00` and no later than `2038-01-19T03:14:07+00:00`.

**How rows are imported**
* If any row is invalid, the request returns a 422 that lists the invalid rows, and no codes are created. At most 20 rows are reported. `errors_truncated` is `true` when more rows are invalid.
* A code that already exists in the store, or that appears earlier in the same file, is skipped and reported in the task's `failure_details`. Codes are compared case-insensitively.

**Notes**
* Only bulk coupon promotions (`coupon_type` of `BULK`) accept imported codes.
* Send the file as `multipart/form-data` in the `importfile` field. The file name must end in `.csv`.
* The whole request body, including multipart encoding, must be no larger than 20 MB (20,971,520 bytes).
* A store can run one import at a time. While an import is `queued` or `processing`, another upload returns a 429 before its contents are validated. An import that is still `queued` or `processing` more than 24 hours after it was created is treated as abandoned, and a new upload can start.
* Uploading the same file as the store's latest import returns a 422, unless that import failed or was abandoned. Files are compared by content, so this applies even when the promotion differs.
* The default rate limit for this endpoint is 3 concurrent requests.

Reference: https://docs.bigcommerce.com/developer/api-reference/rest/admin/management/promotions/coupon-codes-bulk/import-promotion-codes

## Authentication

- `X-Auth-Token` header (required) — ### OAuth scopes | UI Name | Permission | Parameter | |:--------|:-----------|:----------| | Marketing | modify | `store_v2_marketing` | | Marketing | read-only | `store_v2_marketing_read_only` | ### Authentication header | Header | Argument | Description | |:-------|:---------|:------------| | `X-Auth-Token` | `access_token` | For more about API accounts that generate `access_token`s, see [API Accounts and OAuth Scopes](/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). For more about BigCommerce OAuth scopes, see [API Accounts and OAuth Scopes](/developer/docs/overview/api-fundamentals/api-accounts#api-accounts). For a list of API status codes, see [API Status Codes](/developer/api-reference/rest/overview#rest-http-status-codes).

## Request

### Path parameters

- `promotion_id` (string, required) — The ID of the associated promotion.
- `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 (multipart/form-data)

This endpoint expects a multipart form containing a file.

- `importfile` (file, required) — The `.csv` file of coupon codes to import.

## Response

### 200

The promotion task. **Coupon code import tasks** * `completed` means the import created at least one code. It may not have processed every row. If the import stopped early, for example because the promotion was archived, `codes_created` plus `codes_failed` is less than `codes_total`. * `failed` means the import created no codes. `failure_reason` explains why. * An import that is still `queued` or `processing` more than 24 hours after it was created is treated as abandoned. Its `status` does not change, but a new import can start, including one with the same file.

- `data` (PromotionTask, optional) — A long-running operation performed on a promotion, such as a coupon code import.
- `meta` (PromotionsPromotionIdImportCodesPostResponsesContentApplicationJsonSchemaMeta, optional) — Empty meta object, which may be used at a later time.

## Errors

### 404 Not Found Error

The promotion does not exist or has been deleted.

- `status` (integer, required) — The HTTP status code.
- `title` (string, required) — A description of the error.
- `type` (string, required) — A link to the list of BigCommerce API status codes.
- `errors` (PromotionImportErrorResponseErrors, optional) — The rows that failed validation. Only present on a 422 when one or more rows of the uploaded file fail validation.

### 413 Content Too Large Error

The request body is larger than 20 MB.

- `status` (integer, required) — The HTTP status code.
- `title` (string, required) — A description of the error.
- `type` (string, required) — A link to the list of BigCommerce API status codes.
- `errors` (PromotionImportErrorResponseErrors, optional) — The rows that failed validation. Only present on a 422 when one or more rows of the uploaded file fail validation.

### 422 Unprocessable Entity Error

The import was rejected and no codes were created. When rows fail validation, `errors.rows` lists up to 20 invalid rows. Other failures return only a `title`.

- `status` (integer, required) — The HTTP status code.
- `title` (string, required) — A description of the error.
- `type` (string, required) — A link to the list of BigCommerce API status codes.
- `errors` (PromotionImportErrorResponseErrors, optional) — The rows that failed validation. Only present on a 422 when one or more rows of the uploaded file fail validation.

### 429 Too Many Requests Error

Another coupon code import is already queued or processing for the store, and was created less than 24 hours ago. A plain-text 429 is returned instead when more than 3 import requests are in progress at the same time.

- `status` (integer, required) — The HTTP status code.
- `title` (string, required) — A description of the error.
- `type` (string, required) — A link to the list of BigCommerce API status codes.
- `errors` (PromotionImportErrorResponseErrors, optional) — The rows that failed validation. Only present on a 422 when one or more rows of the uploaded file fail validation.

### 500 Internal Server Error

An internal error occurred while starting the import.

- `status` (integer, required) — The HTTP status code.
- `title` (string, required) — A description of the error.
- `type` (string, required) — A link to the list of BigCommerce API status codes.
- `errors` (PromotionImportErrorResponseErrors, optional) — The rows that failed validation. Only present on a 422 when one or more rows of the uploaded file fail validation.

## Types

### PromotionTask

A long-running operation performed on a promotion, such as a coupon code import.

- `promotion_id` (integer, required) — The ID of the promotion the task belongs to.
- `status` (enum, required) — The current status of the task. * `queued`: The task is waiting to start. * `processing`: The task is running. * `completed`: The task finished. * `failed`: The task failed. `failure_reason` explains why.
  - Allowed values: `queued`, `processing`, `completed`, `failed`
- `import` (PromotionTaskImport, required) — The progress of a coupon code import.
- `created_at` (datetime, required) — The date and time the task was created, in RFC 3339 format.
- `finished_at` (datetime, required, nullable) — The date and time the task completed or failed, in RFC 3339 format. `null` while the task is queued or processing.
- `failure_reason` (string, required, nullable) — Why the task failed. `null` unless `status` is `failed`. Possible values: * `No codes were created from the uploaded file`: The import read the whole file but created no codes, for example because every code already exists or the file has no rows. * `The promotion no longer exists`: The promotion was deleted before any codes were created. * `The promotion was archived during the import`: The promotion was archived before any codes were created. * `Codes can only be imported into a bulk coupon promotion`: The promotion stopped being a bulk coupon promotion before any codes were created. * `The import file could not be read` * `The import stopped after repeated failures` * `The import could not be started due to invalid parameters`

### PromotionsPromotionIdImportCodesPostResponsesContentApplicationJsonSchemaMeta

Empty meta object, which may be used at a later time.

### PromotionImportErrorResponseErrors

The rows that failed validation. Only present on a 422 when one or more rows of the uploaded file fail validation.

- `rows` (list of PromotionImportRowError, optional) — The rows that failed validation, in the order they appear in the file. At most 20 rows are reported.
- `errors_truncated` (boolean, optional) — Whether more than 20 rows failed validation.

### PromotionTaskImport

The progress and failure details of a coupon code import.

- `codes_total` (integer, required) — The number of rows of codes in the imported file, not counting the header or blank lines.
- `codes_created` (integer, required) — The number of codes created so far.
- `codes_failed` (integer, required) — The number of codes that were not created, including skipped duplicates.
- `failure_details` (list of PromotionTaskImportFailureDetailsItems, required) — Why codes were not created. Contains at most one entry of each kind.

### PromotionImportRowError

Every validation failure found on one row of the uploaded file.

- `row` (integer, required) — The line number of the row in the uploaded file. The header is line 1, and blank lines are counted.
- `messages` (list of string, required) — The validation failures found on this row.

### PromotionTaskImportFailureDetailsItems

- Promotion Task Import Duplicate Failure Detail: PromotionTaskImportDuplicateFailureDetail
- Promotion Task Import Row Failure Detail: PromotionTaskImportRowFailureDetail

### PromotionTaskImportDuplicateFailureDetail

Codes that were skipped because they already exist in the store or appear earlier in the same file. Codes are compared case-insensitively.

- `message` (enum, required) — A description of the failure.
  - Allowed values: `Duplicate codes found`
- `codes` (list of string, required) — The skipped codes, as written in the file. At most 100 codes are listed. `codes_failed` includes every skipped code.

### PromotionTaskImportRowFailureDetail

Rows that were never processed because the import stopped after repeated failures.

- `message` (enum, required) — A description of the failure.
  - Allowed values: `Some codes could not be imported after repeated failures`
- `first_occurrence_row` (integer, required) — The line number in the imported file of the first row that could not be imported. The header is line 1.
- `count` (integer, required) — The number of rows that could not be imported.

## Examples

### Queued

**Request**

```json
{
  "importfile": "<file: string>"
}
```

**Response**

```json
{
  "data": {
    "promotion_id": 678,
    "status": "queued",
    "import": {
      "codes_total": 50000,
      "codes_created": 0,
      "codes_failed": 0,
      "failure_details": []
    },
    "created_at": "2026-09-07T09:12:04+00:00",
    "finished_at": null,
    "failure_reason": null
  },
  "meta": {}
}
```

**SDK Code**

```python Queued
import requests

url = "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

files = { "importfile": "open('string', 'rb')" }
headers = {
    "Accept": "application/json",
    "X-Auth-Token": "<apiKey>"
}

response = requests.post(url, files=files, headers=headers)

print(response.json())
```

```javascript Queued
const url = 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes';
const form = new FormData();
form.append('importfile', 'string');

const options = {
  method: 'POST',
  headers: {Accept: 'application/json', 'X-Auth-Token': '<apiKey>'}
};

options.body = form;

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

```go Queued
package main

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

func main() {

	url := "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")

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

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

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

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

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

}
```

```ruby Queued
require 'uri'
require 'net/http'

url = URI("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")

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

request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["X-Auth-Token"] = '<apiKey>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n"

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

```java Queued
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")
  .header("Accept", "application/json")
  .header("X-Auth-Token", "<apiKey>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php Queued
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes', [
  'multipart' => [
    [
        'name' => 'importfile',
        'filename' => 'string',
        'contents' => null
    ]
  ]
  'headers' => [
    'Accept' => 'application/json',
    'X-Auth-Token' => '<apiKey>',
  ],
]);

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

```csharp Queued
using RestSharp;

var client = new RestClient("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-Auth-Token", "<apiKey>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Queued
import Foundation

let headers = [
  "Accept": "application/json",
  "X-Auth-Token": "<apiKey>"
]
let parameters = [
  [
    "name": "importfile",
    "fileName": "string"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
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()
```

### Processing

**Request**

```json
{
  "importfile": "<file: string>"
}
```

**Response**

```json
{
  "data": {
    "promotion_id": 678,
    "status": "processing",
    "import": {
      "codes_total": 50000,
      "codes_created": 31000,
      "codes_failed": 2,
      "failure_details": [
        {
          "codes": [
            "SUMMER10",
            "summer11"
          ],
          "message": "Duplicate codes found"
        }
      ]
    },
    "created_at": "2026-09-07T09:12:04+00:00",
    "finished_at": null,
    "failure_reason": null
  },
  "meta": {}
}
```

**SDK Code**

```python Processing
import requests

url = "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

files = { "importfile": "open('string', 'rb')" }
headers = {
    "Accept": "application/json",
    "X-Auth-Token": "<apiKey>"
}

response = requests.post(url, files=files, headers=headers)

print(response.json())
```

```javascript Processing
const url = 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes';
const form = new FormData();
form.append('importfile', 'string');

const options = {
  method: 'POST',
  headers: {Accept: 'application/json', 'X-Auth-Token': '<apiKey>'}
};

options.body = form;

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

```go Processing
package main

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

func main() {

	url := "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")

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

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

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

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

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

}
```

```ruby Processing
require 'uri'
require 'net/http'

url = URI("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")

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

request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["X-Auth-Token"] = '<apiKey>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n"

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

```java Processing
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")
  .header("Accept", "application/json")
  .header("X-Auth-Token", "<apiKey>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php Processing
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes', [
  'multipart' => [
    [
        'name' => 'importfile',
        'filename' => 'string',
        'contents' => null
    ]
  ]
  'headers' => [
    'Accept' => 'application/json',
    'X-Auth-Token' => '<apiKey>',
  ],
]);

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

```csharp Processing
using RestSharp;

var client = new RestClient("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-Auth-Token", "<apiKey>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Processing
import Foundation

let headers = [
  "Accept": "application/json",
  "X-Auth-Token": "<apiKey>"
]
let parameters = [
  [
    "name": "importfile",
    "fileName": "string"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
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()
```

### Completed

**Request**

```json
{
  "importfile": "<file: string>"
}
```

**Response**

```json
{
  "data": {
    "promotion_id": 678,
    "status": "completed",
    "import": {
      "codes_total": 50000,
      "codes_created": 49998,
      "codes_failed": 2,
      "failure_details": [
        {
          "codes": [
            "SUMMER10",
            "summer11"
          ],
          "message": "Duplicate codes found"
        }
      ]
    },
    "created_at": "2026-09-07T09:12:04+00:00",
    "finished_at": "2026-09-07T09:18:41+00:00",
    "failure_reason": null
  },
  "meta": {}
}
```

**SDK Code**

```python Completed
import requests

url = "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

files = { "importfile": "open('string', 'rb')" }
headers = {
    "Accept": "application/json",
    "X-Auth-Token": "<apiKey>"
}

response = requests.post(url, files=files, headers=headers)

print(response.json())
```

```javascript Completed
const url = 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes';
const form = new FormData();
form.append('importfile', 'string');

const options = {
  method: 'POST',
  headers: {Accept: 'application/json', 'X-Auth-Token': '<apiKey>'}
};

options.body = form;

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

```go Completed
package main

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

func main() {

	url := "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")

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

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

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

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

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

}
```

```ruby Completed
require 'uri'
require 'net/http'

url = URI("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")

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

request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["X-Auth-Token"] = '<apiKey>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n"

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

```java Completed
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")
  .header("Accept", "application/json")
  .header("X-Auth-Token", "<apiKey>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php Completed
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes', [
  'multipart' => [
    [
        'name' => 'importfile',
        'filename' => 'string',
        'contents' => null
    ]
  ]
  'headers' => [
    'Accept' => 'application/json',
    'X-Auth-Token' => '<apiKey>',
  ],
]);

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

```csharp Completed
using RestSharp;

var client = new RestClient("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-Auth-Token", "<apiKey>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Completed
import Foundation

let headers = [
  "Accept": "application/json",
  "X-Auth-Token": "<apiKey>"
]
let parameters = [
  [
    "name": "importfile",
    "fileName": "string"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
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()
```

### Completed after stopping early

**Request**

```json
{
  "importfile": "<file: string>"
}
```

**Response**

```json
{
  "data": {
    "promotion_id": 678,
    "status": "completed",
    "import": {
      "codes_total": 50000,
      "codes_created": 19000,
      "codes_failed": 0,
      "failure_details": []
    },
    "created_at": "2026-09-07T09:12:04+00:00",
    "finished_at": "2026-09-07T09:12:28+00:00",
    "failure_reason": null
  },
  "meta": {}
}
```

**SDK Code**

```python Completed after stopping early
import requests

url = "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

files = { "importfile": "open('string', 'rb')" }
headers = {
    "Accept": "application/json",
    "X-Auth-Token": "<apiKey>"
}

response = requests.post(url, files=files, headers=headers)

print(response.json())
```

```javascript Completed after stopping early
const url = 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes';
const form = new FormData();
form.append('importfile', 'string');

const options = {
  method: 'POST',
  headers: {Accept: 'application/json', 'X-Auth-Token': '<apiKey>'}
};

options.body = form;

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

```go Completed after stopping early
package main

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

func main() {

	url := "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")

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

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

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

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

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

}
```

```ruby Completed after stopping early
require 'uri'
require 'net/http'

url = URI("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")

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

request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["X-Auth-Token"] = '<apiKey>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n"

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

```java Completed after stopping early
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")
  .header("Accept", "application/json")
  .header("X-Auth-Token", "<apiKey>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php Completed after stopping early
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes', [
  'multipart' => [
    [
        'name' => 'importfile',
        'filename' => 'string',
        'contents' => null
    ]
  ]
  'headers' => [
    'Accept' => 'application/json',
    'X-Auth-Token' => '<apiKey>',
  ],
]);

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

```csharp Completed after stopping early
using RestSharp;

var client = new RestClient("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-Auth-Token", "<apiKey>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Completed after stopping early
import Foundation

let headers = [
  "Accept": "application/json",
  "X-Auth-Token": "<apiKey>"
]
let parameters = [
  [
    "name": "importfile",
    "fileName": "string"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
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()
```

### Failed

**Request**

```json
{
  "importfile": "<file: string>"
}
```

**Response**

```json
{
  "data": {
    "promotion_id": 678,
    "status": "failed",
    "import": {
      "codes_total": 3,
      "codes_created": 0,
      "codes_failed": 3,
      "failure_details": [
        {
          "codes": [
            "SUMMER10",
            "summer10",
            "SUMMER11"
          ],
          "message": "Duplicate codes found"
        }
      ]
    },
    "created_at": "2026-09-07T09:12:04+00:00",
    "finished_at": "2026-09-07T09:12:05+00:00",
    "failure_reason": "No codes were created from the uploaded file"
  },
  "meta": {}
}
```

**SDK Code**

```python Failed
import requests

url = "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

files = { "importfile": "open('string', 'rb')" }
headers = {
    "Accept": "application/json",
    "X-Auth-Token": "<apiKey>"
}

response = requests.post(url, files=files, headers=headers)

print(response.json())
```

```javascript Failed
const url = 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes';
const form = new FormData();
form.append('importfile', 'string');

const options = {
  method: 'POST',
  headers: {Accept: 'application/json', 'X-Auth-Token': '<apiKey>'}
};

options.body = form;

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

```go Failed
package main

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

func main() {

	url := "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")

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

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

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

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

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

}
```

```ruby Failed
require 'uri'
require 'net/http'

url = URI("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")

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

request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["X-Auth-Token"] = '<apiKey>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n"

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

```java Failed
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")
  .header("Accept", "application/json")
  .header("X-Auth-Token", "<apiKey>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php Failed
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes', [
  'multipart' => [
    [
        'name' => 'importfile',
        'filename' => 'string',
        'contents' => null
    ]
  ]
  'headers' => [
    'Accept' => 'application/json',
    'X-Auth-Token' => '<apiKey>',
  ],
]);

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

```csharp Failed
using RestSharp;

var client = new RestClient("https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-Auth-Token", "<apiKey>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"importfile\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Failed
import Foundation

let headers = [
  "Accept": "application/json",
  "X-Auth-Token": "<apiKey>"
]
let parameters = [
  [
    "name": "importfile",
    "fileName": "string"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.bigcommerce.com/stores/store_hash/v3/promotions/promotion_id/import-codes")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
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()
```