curl --request POST \
--url https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'X-Customer-IP: <x-customer-ip>' \
--data '
{
"revision": 156,
"fromCurrency": "MXN",
"toCurrency": "USD",
"toCurrencyAmount": 100000,
"endAt": "2024-02-23",
"rate": 20.616512,
"externalTransactionId": "780231b3ae0d7e9e5097nd89",
"extraFields": {
"field_a": "value_a",
"field_b": "value_b"
}
}
'import requests
url = "https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote"
payload = {
"revision": 156,
"fromCurrency": "MXN",
"toCurrency": "USD",
"toCurrencyAmount": 100000,
"endAt": "2024-02-23",
"rate": 20.616512,
"externalTransactionId": "780231b3ae0d7e9e5097nd89",
"extraFields": {
"field_a": "value_a",
"field_b": "value_b"
}
}
headers = {
"X-Customer-IP": "<x-customer-ip>",
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Customer-IP': '<x-customer-ip>',
Authorization: 'Basic <encoded-value>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
revision: 156,
fromCurrency: 'MXN',
toCurrency: 'USD',
toCurrencyAmount: 100000,
endAt: '2024-02-23',
rate: 20.616512,
externalTransactionId: '780231b3ae0d7e9e5097nd89',
extraFields: {field_a: 'value_a', field_b: 'value_b'}
})
};
fetch('https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'revision' => 156,
'fromCurrency' => 'MXN',
'toCurrency' => 'USD',
'toCurrencyAmount' => 100000,
'endAt' => '2024-02-23',
'rate' => 20.616512,
'externalTransactionId' => '780231b3ae0d7e9e5097nd89',
'extraFields' => [
'field_a' => 'value_a',
'field_b' => 'value_b'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json",
"X-Customer-IP: <x-customer-ip>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote"
payload := strings.NewReader("{\n \"revision\": 156,\n \"fromCurrency\": \"MXN\",\n \"toCurrency\": \"USD\",\n \"toCurrencyAmount\": 100000,\n \"endAt\": \"2024-02-23\",\n \"rate\": 20.616512,\n \"externalTransactionId\": \"780231b3ae0d7e9e5097nd89\",\n \"extraFields\": {\n \"field_a\": \"value_a\",\n \"field_b\": \"value_b\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Customer-IP", "<x-customer-ip>")
req.Header.Add("Authorization", "Basic <encoded-value>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote")
.header("X-Customer-IP", "<x-customer-ip>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"revision\": 156,\n \"fromCurrency\": \"MXN\",\n \"toCurrency\": \"USD\",\n \"toCurrencyAmount\": 100000,\n \"endAt\": \"2024-02-23\",\n \"rate\": 20.616512,\n \"externalTransactionId\": \"780231b3ae0d7e9e5097nd89\",\n \"extraFields\": {\n \"field_a\": \"value_a\",\n \"field_b\": \"value_b\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Customer-IP"] = '<x-customer-ip>'
request["Authorization"] = 'Basic <encoded-value>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"revision\": 156,\n \"fromCurrency\": \"MXN\",\n \"toCurrency\": \"USD\",\n \"toCurrencyAmount\": 100000,\n \"endAt\": \"2024-02-23\",\n \"rate\": 20.616512,\n \"externalTransactionId\": \"780231b3ae0d7e9e5097nd89\",\n \"extraFields\": {\n \"field_a\": \"value_a\",\n \"field_b\": \"value_b\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "1b0ada1e-fa1b-4cfe-a553-01b340c5650e",
"transactionId": "4d78ac65-2c3f-47e2-8bf3-3f76124e9d27"
}{
"message": "REVISION_INVALID",
"reason": "The revision number is not valid or does not exist. Please fetch a new rate table using the /offline-rates endpoint and pass a valid revision."
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "REVISION_EXPIRED",
"reason": "The revision number has expired. Please fetch a new rate table using the /offline-rates endpoint."
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "Could not parse IP address (v4 or v6) for ip"
}Accept
Accepts a previously retrieved offline rate proposal and books the hedge accordingly.
curl --request POST \
--url https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'X-Customer-IP: <x-customer-ip>' \
--data '
{
"revision": 156,
"fromCurrency": "MXN",
"toCurrency": "USD",
"toCurrencyAmount": 100000,
"endAt": "2024-02-23",
"rate": 20.616512,
"externalTransactionId": "780231b3ae0d7e9e5097nd89",
"extraFields": {
"field_a": "value_a",
"field_b": "value_b"
}
}
'import requests
url = "https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote"
payload = {
"revision": 156,
"fromCurrency": "MXN",
"toCurrency": "USD",
"toCurrencyAmount": 100000,
"endAt": "2024-02-23",
"rate": 20.616512,
"externalTransactionId": "780231b3ae0d7e9e5097nd89",
"extraFields": {
"field_a": "value_a",
"field_b": "value_b"
}
}
headers = {
"X-Customer-IP": "<x-customer-ip>",
"Authorization": "Basic <encoded-value>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Customer-IP': '<x-customer-ip>',
Authorization: 'Basic <encoded-value>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
revision: 156,
fromCurrency: 'MXN',
toCurrency: 'USD',
toCurrencyAmount: 100000,
endAt: '2024-02-23',
rate: 20.616512,
externalTransactionId: '780231b3ae0d7e9e5097nd89',
extraFields: {field_a: 'value_a', field_b: 'value_b'}
})
};
fetch('https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'revision' => 156,
'fromCurrency' => 'MXN',
'toCurrency' => 'USD',
'toCurrencyAmount' => 100000,
'endAt' => '2024-02-23',
'rate' => 20.616512,
'externalTransactionId' => '780231b3ae0d7e9e5097nd89',
'extraFields' => [
'field_a' => 'value_a',
'field_b' => 'value_b'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Basic <encoded-value>",
"Content-Type: application/json",
"X-Customer-IP: <x-customer-ip>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote"
payload := strings.NewReader("{\n \"revision\": 156,\n \"fromCurrency\": \"MXN\",\n \"toCurrency\": \"USD\",\n \"toCurrencyAmount\": 100000,\n \"endAt\": \"2024-02-23\",\n \"rate\": 20.616512,\n \"externalTransactionId\": \"780231b3ae0d7e9e5097nd89\",\n \"extraFields\": {\n \"field_a\": \"value_a\",\n \"field_b\": \"value_b\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Customer-IP", "<x-customer-ip>")
req.Header.Add("Authorization", "Basic <encoded-value>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote")
.header("X-Customer-IP", "<x-customer-ip>")
.header("Authorization", "Basic <encoded-value>")
.header("Content-Type", "application/json")
.body("{\n \"revision\": 156,\n \"fromCurrency\": \"MXN\",\n \"toCurrency\": \"USD\",\n \"toCurrencyAmount\": 100000,\n \"endAt\": \"2024-02-23\",\n \"rate\": 20.616512,\n \"externalTransactionId\": \"780231b3ae0d7e9e5097nd89\",\n \"extraFields\": {\n \"field_a\": \"value_a\",\n \"field_b\": \"value_b\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.grainfinance.co/v1/customers/{customerId}/hedges/accept-offline-quote")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Customer-IP"] = '<x-customer-ip>'
request["Authorization"] = 'Basic <encoded-value>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"revision\": 156,\n \"fromCurrency\": \"MXN\",\n \"toCurrency\": \"USD\",\n \"toCurrencyAmount\": 100000,\n \"endAt\": \"2024-02-23\",\n \"rate\": 20.616512,\n \"externalTransactionId\": \"780231b3ae0d7e9e5097nd89\",\n \"extraFields\": {\n \"field_a\": \"value_a\",\n \"field_b\": \"value_b\"\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "1b0ada1e-fa1b-4cfe-a553-01b340c5650e",
"transactionId": "4d78ac65-2c3f-47e2-8bf3-3f76124e9d27"
}{
"message": "REVISION_INVALID",
"reason": "The revision number is not valid or does not exist. Please fetch a new rate table using the /offline-rates endpoint and pass a valid revision."
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "REVISION_EXPIRED",
"reason": "The revision number has expired. Please fetch a new rate table using the /offline-rates endpoint."
}{
"message": "Can't perform this action",
"reason": "Supplied object is in *Cancelled* state, which prevents performing this action"
}{
"message": "Could not parse IP address (v4 or v6) for ip"
}Authorizations
Basic authentication using the partner API keys from https://console.grainfinance.co/keys
Headers
The IPv4 address of the browser from which the customer contacts your platform.
example: 192.158.1.38
((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}Path Parameters
The id of the customer within the Grain platform.
[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}Body
The payload required in order to accept an offline rate proposal and book the hedge.
The id of the revision that defines the accepted rate for the currency-pair and tenor.
156
The currency in which the transaction should be paid at by your customer.
^[A-Z]{3}$"MXN"
the currency you want to buy.
^[A-Z]{3}$"USD"
The amount to hedge in the toCurrency.
100000
The date in which the hedge will be settled, denoted in YYYY-MM-DD format.
\d{4}-\d{2}-\d{2}"2024-02-23"
Represents the exchange rate according to the offline map of currency pairs to tenor object.
The calculation of the tenor is based on the difference in calendar days between the 'tenorCalculationDate' and the 'endAt' date:
- If the number of calendar days from 'tenorCalculationDate' to
endAtis less than or equal to 7, the tenor is 7 days. - If the number of calendar days from 'tenorCalculationDate' to
endAtis greater than 7 and less than or equal to 14, the tenor is 14 days. - If the number of calendar days from 'tenorCalculationDate' to
endAtis greater than 14 and less than or equal to 30, the tenor is 30 days. - If the number of calendar days from 'tenorCalculationDate' to
endAtis greater than 30 and less than or equal to 60, the tenor is 60 days. - ...
- If the number of calendar days from 'tenorCalculationDate' to
endAtis greater than 330 and less than or equal to 360, the tenor is 360 days.
When counting the difference in calendar days, every day is counted as one regardless of the duration of the day. This means that the calculation includes all days: weekends, holidays, and weekdays alike.
For example, if the 'endAt' date is 2023-12-16 and the 'tenorCalculationDate' is 2024-12-15, the result is 1 calendar day.
To calculate the difference in calendar days accurately, we recommend using a date manipulation library, such as date-fns and its differenceInCalendarDays function, or a similar feature provided by other date libraries.
20.616512
Optional The transaction id, as identified within your system.
"780231b3ae0d7e9e5097nd89"
Additional fields that provide further details about the transaction. These fields should be specified as a valid JSON object.
Show child attributes
Show child attributes
{
"field_a": "value_a",
"field_b": "value_b"
}
Response
Hedge Accepted
The response of accepting an offline rate for a hedge.
The id of the created object.
[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}"1b0ada1e-fa1b-4cfe-a553-01b340c5650e"
The id of the transaction within the Grain platform.
[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}"4d78ac65-2c3f-47e2-8bf3-3f76124e9d27"