> This page is for Afterpay Partner API.

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

# Approve Custom Rate

POST https://agencyapi.afterpay.com/v1/custom-rate/{customRateId}/review
Content-Type: application/json

Partners can set up a unique, custom buy-rate for a unique managed seller, such as enterprise, mid-market, or a platform. To set up a custom rate, Afterpay teams will create a custom rate via internal Afterpay tooling.

Reference: https://developers.afterpay.com/afterpay-partner-api/api-reference/reference-partner-api/rates/review-custom-rate

## Servers

- `https://agencyapi.afterpay.com` (Production, default)
- `https://agencyapi.sandbox.afterpay.com` (Sandbox)

## Request

### Path parameters

- `customRateId` (string, required) — ID of the custom rate to approve

### Headers

- `Accept` (string, required, default: application/json) — Specifies media types that are acceptable for the response.

### Body (application/json)

This endpoint expects an object.

- `customRateId` (string, required) — The unique ID for the custom rate between Afterpay and the partner.
- `userDetails` (User, required)
- `comment` (string, required) — Comment specific to the custom rate request.
- `status` (enum, required) — The de facto approval field that determines whether the rate request by Afterpay is approved or rejected by the partner.
  - Allowed values: `APPROVED`, `REJECTED`
- `customRateType` (enum, required) — Defines whether the custom rate applies to only one seller or applies to multiple sellers under the same platform or brand.
  - Allowed values: `MERCHANT`, `BRAND`
- `merchantId` (string, required) — Afterpay merchant id MID; this will only be available for existing sellers; for new sellers please use the reference field.
- `reference` (string, required) — Seller or brand reference to which the custom rate is being applied; this defines the unique seller or the unique platform or brand and iswill be requested from the partner manually before the custom rate request is created.
- `rateDetails` (V1CustomRateCustomRateIdReviewPostRequestBodyContentApplicationJsonSchemaRateDetails, required)

## Response

### 200

Custom rate reviewed successfully

- `timestamp` (string, optional) — Datetime field indicating when the custom rate request was actioned, returned using the standard ISO 8601 format, in UTC Coordinated Universal Time).
- `error` (string, optional) — Shows any errors encountered on the response to the contract approval call.
- `message` (string, optional) — Any message that may be attached to the response.
- `customRateDetails` (CustomRate, optional)

## Errors

### 400 Bad Request Error

Bad Request

- `timestamp` (string, optional) — Timestamp of the response.
- `status` (integer, optional) — The HTTP status code.
- `error` (string, optional) — Name of the error that occurred.
- `message` (string, optional) — A human-readable message which provides more details about the error.
- `path` (string, optional) — The attempted endpoint.

### 401 Unauthorized Error

Unauthorized, e.g., HMAC verification failed.

- `timestamp` (string, optional) — Timestamp of the response.
- `status` (integer, optional) — The HTTP status code.
- `error` (string, optional) — Name of the error that occurred.
- `message` (string, optional) — A human-readable message which provides more details about the error.
- `path` (string, optional) — The attempted endpoint.

### 404 Not Found Error

Not Found - The specified resource was not found.

- `timestamp` (string, optional) — Timestamp of the response, indicating when the error occurred.
- `status` (integer, optional) — The HTTP status code, specifically indicating a 404 error in this case.
- `error` (string, optional) — A short description of the error, typically "Not Found" for a 404 response.
- `message` (string, optional) — A human-readable message providing more details about the error.
- `path` (string, optional) — The attempted endpoint path that resulted in the 404 error.

### 503 Service Unavailable Error

Service unavailable.

- `timestamp` (string, optional) — Timestamp of the response.
- `status` (integer, optional) — The HTTP status code.
- `error` (string, optional) — Name of the error that occurred.
- `message` (string, optional) — A human-readable message which provides more details about the error.
- `path` (string, optional) — The attempted endpoint.

## Types

### User

- `firstName` (string, required) — Given name of the user who is actioning Afterpay's contract request.
- `lastName` (string, required) — Surname of the user who is actioning Afterpay's contract request.
- `email` (string, required) — Email of the user.
- `adminIdentifier` (string, optional, nullable) — Optional identifier for the admin..

### V1CustomRateCustomRateIdReviewPostRequestBodyContentApplicationJsonSchemaRateDetails

- `countryCode` (string, required) — Country code in the two-letter ISO 3166-1 alpha-2 standard format, defining the consumer market for which the rate applies.
- `rates` (list of V1CustomRateCustomRateIdReviewPostRequestBodyContentApplicationJsonSchemaRateDetailsRatesItems, required)

### CustomRate

- `customRateId` (string, optional) — The unique ID for the custom rate that was actioned for a seller.
- `status` (enum, optional) — Custom rate status.
  - Allowed values: `APPROVED`, `PENDING`, `REJECTED`
- `customRateType` (enum, optional) — Defines whether the custom rate applies to only one seller or applies to multiple sellers under the same platform or brand.
  - Allowed values: `MERCHANT`, `BRAND`
- `reference` (string, optional) — Seller or brand reference to which the custom rate is being applied; this defines the unique seller or the unique platform or brand and will be requested from the partner manually before the custom rate request is created.
- `effectiveFrom` (string, optional) — Datetime this custom rate is effective from.

### V1CustomRateCustomRateIdReviewPostRequestBodyContentApplicationJsonSchemaRateDetailsRatesItems

- `variableRatePercentage` (double, required) — Variable part of the buy-rate.
- `fixedRate` (double, required) — Fixed part of the buy-rate.
- `fixedRateCurrencyCode` (string, required) — Currency of the fixed part of the buy-rate.
- `rateType` (enum, required) — INTRODUCTORY for temporary promotional rate or ONGOING for steady-state rate.
  - Allowed values: `INTRODUCTORY`, `ONGOING`
- `durationInMonths` (integer, required) — Number of months that the introductory rate will be applied.

## Examples

**Request**

```json
{
  "customRateId": "712123123556455",
  "userDetails": {
    "firstName": "John",
    "lastName": "PSP",
    "email": "john.psp@psp.com"
  },
  "comment": "Approved by X on date Y for reason Z.",
  "status": "APPROVED",
  "customRateType": "MERCHANT",
  "merchantId": "100405604504",
  "reference": "ac_advkasdvasfbaadf:US",
  "rateDetails": {
    "countryCode": "US",
    "rates": [
      {
        "variableRatePercentage": 5,
        "fixedRate": 0.3,
        "fixedRateCurrencyCode": "USD",
        "rateType": "ONGOING",
        "durationInMonths": 3
      }
    ]
  }
}
```

**Response**

```json
{
  "timestamp": "2023-08-17T21:41:47.341+00:00",
  "error": "string",
  "message": "string",
  "customRateDetails": {
    "customRateId": "785389121238",
    "status": "APPROVED",
    "customRateType": "MERCHANT",
    "reference": "ac_advkasdvasfbaadf:US",
    "effectiveFrom": "2023-08-17T21:41:47.341+00:00"
  }
}
```

**SDK Code**

```python
import requests

url = "https://agencyapi.afterpay.com/v1/custom-rate/123457838/review"

payload = {
    "customRateId": "712123123556455",
    "userDetails": {
        "firstName": "John",
        "lastName": "PSP",
        "email": "john.psp@psp.com"
    },
    "comment": "Approved by X on date Y for reason Z.",
    "status": "APPROVED",
    "customRateType": "MERCHANT",
    "merchantId": "100405604504",
    "reference": "ac_advkasdvasfbaadf:US",
    "rateDetails": {
        "countryCode": "US",
        "rates": [
            {
                "variableRatePercentage": 5,
                "fixedRate": 0.3,
                "fixedRateCurrencyCode": "USD",
                "rateType": "ONGOING",
                "durationInMonths": 3
            }
        ]
    }
}
headers = {
    "Accept": "application/json",
    "User-Agent": "User-Agent",
    "Content-Type": "application/json"
}

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

print(response.json())
```

```javascript
const url = 'https://agencyapi.afterpay.com/v1/custom-rate/123457838/review';
const options = {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'User-Agent': 'User-Agent',
    'Content-Type': 'application/json'
  },
  body: '{"customRateId":"712123123556455","userDetails":{"firstName":"John","lastName":"PSP","email":"john.psp@psp.com"},"comment":"Approved by X on date Y for reason Z.","status":"APPROVED","customRateType":"MERCHANT","merchantId":"100405604504","reference":"ac_advkasdvasfbaadf:US","rateDetails":{"countryCode":"US","rates":[{"variableRatePercentage":5,"fixedRate":0.3,"fixedRateCurrencyCode":"USD","rateType":"ONGOING","durationInMonths":3}]}}'
};

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

```go
package main

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

func main() {

	url := "https://agencyapi.afterpay.com/v1/custom-rate/123457838/review"

	payload := strings.NewReader("{\n  \"customRateId\": \"712123123556455\",\n  \"userDetails\": {\n    \"firstName\": \"John\",\n    \"lastName\": \"PSP\",\n    \"email\": \"john.psp@psp.com\"\n  },\n  \"comment\": \"Approved by X on date Y for reason Z.\",\n  \"status\": \"APPROVED\",\n  \"customRateType\": \"MERCHANT\",\n  \"merchantId\": \"100405604504\",\n  \"reference\": \"ac_advkasdvasfbaadf:US\",\n  \"rateDetails\": {\n    \"countryCode\": \"US\",\n    \"rates\": [\n      {\n        \"variableRatePercentage\": 5,\n        \"fixedRate\": 0.3,\n        \"fixedRateCurrencyCode\": \"USD\",\n        \"rateType\": \"ONGOING\",\n        \"durationInMonths\": 3\n      }\n    ]\n  }\n}")

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

	req.Header.Add("Accept", "application/json")
	req.Header.Add("User-Agent", "User-Agent")
	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
require 'uri'
require 'net/http'

url = URI("https://agencyapi.afterpay.com/v1/custom-rate/123457838/review")

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

request = Net::HTTP::Post.new(url)
request["Accept"] = 'application/json'
request["User-Agent"] = 'User-Agent'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"customRateId\": \"712123123556455\",\n  \"userDetails\": {\n    \"firstName\": \"John\",\n    \"lastName\": \"PSP\",\n    \"email\": \"john.psp@psp.com\"\n  },\n  \"comment\": \"Approved by X on date Y for reason Z.\",\n  \"status\": \"APPROVED\",\n  \"customRateType\": \"MERCHANT\",\n  \"merchantId\": \"100405604504\",\n  \"reference\": \"ac_advkasdvasfbaadf:US\",\n  \"rateDetails\": {\n    \"countryCode\": \"US\",\n    \"rates\": [\n      {\n        \"variableRatePercentage\": 5,\n        \"fixedRate\": 0.3,\n        \"fixedRateCurrencyCode\": \"USD\",\n        \"rateType\": \"ONGOING\",\n        \"durationInMonths\": 3\n      }\n    ]\n  }\n}"

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

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

HttpResponse<String> response = Unirest.post("https://agencyapi.afterpay.com/v1/custom-rate/123457838/review")
  .header("Accept", "application/json")
  .header("User-Agent", "User-Agent")
  .header("Content-Type", "application/json")
  .body("{\n  \"customRateId\": \"712123123556455\",\n  \"userDetails\": {\n    \"firstName\": \"John\",\n    \"lastName\": \"PSP\",\n    \"email\": \"john.psp@psp.com\"\n  },\n  \"comment\": \"Approved by X on date Y for reason Z.\",\n  \"status\": \"APPROVED\",\n  \"customRateType\": \"MERCHANT\",\n  \"merchantId\": \"100405604504\",\n  \"reference\": \"ac_advkasdvasfbaadf:US\",\n  \"rateDetails\": {\n    \"countryCode\": \"US\",\n    \"rates\": [\n      {\n        \"variableRatePercentage\": 5,\n        \"fixedRate\": 0.3,\n        \"fixedRateCurrencyCode\": \"USD\",\n        \"rateType\": \"ONGOING\",\n        \"durationInMonths\": 3\n      }\n    ]\n  }\n}")
  .asString();
```

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

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://agencyapi.afterpay.com/v1/custom-rate/123457838/review', [
  'body' => '{
  "customRateId": "712123123556455",
  "userDetails": {
    "firstName": "John",
    "lastName": "PSP",
    "email": "john.psp@psp.com"
  },
  "comment": "Approved by X on date Y for reason Z.",
  "status": "APPROVED",
  "customRateType": "MERCHANT",
  "merchantId": "100405604504",
  "reference": "ac_advkasdvasfbaadf:US",
  "rateDetails": {
    "countryCode": "US",
    "rates": [
      {
        "variableRatePercentage": 5,
        "fixedRate": 0.3,
        "fixedRateCurrencyCode": "USD",
        "rateType": "ONGOING",
        "durationInMonths": 3
      }
    ]
  }
}',
  'headers' => [
    'Accept' => 'application/json',
    'Content-Type' => 'application/json',
    'User-Agent' => 'User-Agent',
  ],
]);

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

```csharp
using RestSharp;

var client = new RestClient("https://agencyapi.afterpay.com/v1/custom-rate/123457838/review");
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("User-Agent", "User-Agent");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"customRateId\": \"712123123556455\",\n  \"userDetails\": {\n    \"firstName\": \"John\",\n    \"lastName\": \"PSP\",\n    \"email\": \"john.psp@psp.com\"\n  },\n  \"comment\": \"Approved by X on date Y for reason Z.\",\n  \"status\": \"APPROVED\",\n  \"customRateType\": \"MERCHANT\",\n  \"merchantId\": \"100405604504\",\n  \"reference\": \"ac_advkasdvasfbaadf:US\",\n  \"rateDetails\": {\n    \"countryCode\": \"US\",\n    \"rates\": [\n      {\n        \"variableRatePercentage\": 5,\n        \"fixedRate\": 0.3,\n        \"fixedRateCurrencyCode\": \"USD\",\n        \"rateType\": \"ONGOING\",\n        \"durationInMonths\": 3\n      }\n    ]\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Accept": "application/json",
  "User-Agent": "User-Agent",
  "Content-Type": "application/json"
]
let parameters = [
  "customRateId": "712123123556455",
  "userDetails": [
    "firstName": "John",
    "lastName": "PSP",
    "email": "john.psp@psp.com"
  ],
  "comment": "Approved by X on date Y for reason Z.",
  "status": "APPROVED",
  "customRateType": "MERCHANT",
  "merchantId": "100405604504",
  "reference": "ac_advkasdvasfbaadf:US",
  "rateDetails": [
    "countryCode": "US",
    "rates": [
      [
        "variableRatePercentage": 5,
        "fixedRate": 0.3,
        "fixedRateCurrencyCode": "USD",
        "rateType": "ONGOING",
        "durationInMonths": 3
      ]
    ]
  ]
] as [String : Any]

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

let request = NSMutableURLRequest(url: NSURL(string: "https://agencyapi.afterpay.com/v1/custom-rate/123457838/review")! 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()
```