We use a handful of security mechanisms to ensure that your requests are secure. You can find information on how to make a secure authenticated request below.
In order to make an authenticated request you'll need to pass a couple of values through the HTTP headers with your request:
HTTP Header Field | Description |
---|---|
X-Api-Key | Your Wyre API key. Your key can be found at https://dash.sendwyre.com/settings/api-keys |
X-Api-Signature | A signature used to verify the request was sent by the account holder. See Calculating the request signature. |
Additionally, you should include a GET parameter named timestamp
which is the current time in millisecond epoch format. We use this timestamp to help protect against replay attacks.
Calculating the request signature
Calculating the X-Api-Signature
field is a two step process
- Concatenate the request URL with the body of the HTTP request into a UTF-8 String. Use an empty string for the HTTP body in GET requests.
- Compute the signature using HMAC with SHA-256 and your API Secret Key.
If you are sending a GET request you would sign the following:
https://api.sendwyre.com/v2/rates?timestamp=1426252182534
If you are making a POST request you would sign the following:
https://api.sendwyre.com/v2/transfers?timestamp=1426252182534
Note: You must send the request body exactly as you sign it, whitespace and all. The server calculates the signature based on exactly what's in the request body.
<?php
function make_authenticated_request($endpoint, $method, $body) {
$url = 'https://api.sendwyre.com';
$api_key = "bh405n7stsuo5ut30iftrsl71b4iqjnv";
$secret_key = "a19cvrchgja82urvn47kirrlrrb7stgg";
$timestamp = floor(microtime(true)*1000);
$request_url = $url . $endpoint;
if(strpos($request_url,"?"))
$request_url .= '×tamp=' . $timestamp;
else
$request_url .= '?timestamp=' . $timestamp;
if(!empty($body))
$body = json_encode($body, JSON_FORCE_OBJECT);
else
$body = '';
$headers = array(
"Content-Type: application/json",
"X-Api-Key: ". $api_key,
"X-Api-Signature: ". calc_auth_sig_hash($secret_key, $request_url . $body),
"X-Api-Version: 2"
);
$curl = curl_init();
if($method=="POST"){
$options = array(
CURLOPT_URL => $request_url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true);
}else {
$options = array(
CURLOPT_URL => $request_url,
CURLOPT_RETURNTRANSFER => true);
}
curl_setopt_array($curl, $options);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($curl);
curl_close($curl);
var_dump($result);
return json_decode($result, true);
}
function calc_auth_sig_hash($seckey, $val) {
$hash = hash_hmac('sha256', $val, $seckey);
return $hash;
}
echo make_authenticated_request("/account", "GET", array());
$transfer = array(
"sourceCurrency"=>"USD",
"dest"=>"[email protected]",
"destAmount"=> 55.05,
"destCurrency"=>"EUR",
"message"=> "buy sam pizza"
);
echo make_authenticated_request("/transfers", "POST", $transfer);
?>
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Linq;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
namespace testauthwyre
{
class MainClass
{
public static void Main(string[] args)
{
WyreApi wyre = new WyreApi();
HttpWebResponse accountResponse = wyre.Get("/account");
Console.WriteLine(GetResponseBody(accountResponse));
Dictionary<string, object> body = new Dictionary<string, object>();
body.Add("sourceCurrency", "USD");
body.Add("sourceAmount", "10");
body.Add("dest", "[email protected]");
HttpWebResponse transferResponse = wyre.Post("/transfers", body);
Console.WriteLine(GetResponseBody(transferResponse));
}
private static string GetResponseBody(HttpWebResponse response)
{
return JObject.Parse(new StreamReader(response.GetResponseStream()).ReadToEnd()).ToString(Formatting.Indented);
}
}
public class WyreApi
{
private const String domain = "https://api.sendwyre.com";
private const String apiKey = "xxx";
private const String secKey = "xxx";
public HttpWebResponse Get(string path)
{
return Get(path, new Dictionary<string, object>());
}
public HttpWebResponse Get(string path, Dictionary<string, object> queryParams)
{
return Request("GET", path, queryParams);
}
public HttpWebResponse Post(string path, Dictionary<string, object> body)
{
return Request("POST", path, body);
}
private HttpWebResponse Request(string method, string path, Dictionary<string, object> body)
{
Dictionary<string, object> queryParams = new Dictionary<string, object>();
if (method.Equals("GET"))
queryParams = body;
queryParams.Add("timestamp", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
string queryString = queryParams.Aggregate("", (previous, current) => previous + "&" + current.Key + "=" + current.Value).Remove(0, 1);
string url = domain + path + "?" + queryString;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method;
request.ContentType = "application/json";
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
if (!method.Equals("GET"))
{
url += JsonConvert.SerializeObject(body);
using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
writer.Write(JsonConvert.SerializeObject(body));
}
request.Headers["X-Api-Key"] = apiKey;
request.Headers["X-Api-Signature"] = CalcAuthSigHash(secKey, url);
request.Headers["X-Api-Version"] = "2";
try
{
return (HttpWebResponse)request.GetResponse();
}
catch(WebException e)
{
string msg = new StreamReader(e.Response.GetResponseStream()).ReadToEnd();
Console.WriteLine(msg);
throw new SystemException(msg);
}
}
private byte[] GetBytes(string str)
{
return Encoding.UTF8.GetBytes(str);
}
private string GetString(byte[] bytes)
{
return BitConverter.ToString(bytes);
}
private String CalcAuthSigHash(string key, string value)
{
HMACSHA256 hmac = new HMACSHA256(GetBytes(key));
string hash = GetString(hmac.ComputeHash(GetBytes(value))).Replace("-", "");
return hash;
}
}
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.Integer;
import java.lang.String;
import java.lang.StringBuffer;
import java.net.HttpURLConnection;
import java.net.URL;
public class TestAuth {
public static void main(String[] args) {
String apiKey = "PUT YOUR API KEY HERE";
String secretKey = "PUT YOUR SECRET KEY HERE";
String url = "https://api.sendwyre.com/account";
String method = "GET";
String data = "";
String result = executeWyreRequest(url, "", method, apiKey, secretKey);
System.out.println(result);
url = "https://api.sendwyre.com/transfers";
method = "POST";
data = "{" +
" \"dest\": \"[email protected]\"," +
" \"destCurrency\": \"USD\"," +
" \"sourceCurrency\" : \"BTC\"," +
" \"sourceAmount\" : \"1\"," +
" \"message\": \"$1 worth of bitcoin!\"" +
"}";
result = executeWyreRequest(url, data, method, apiKey, secretKey);
System.out.println(result);
}
public static String executeWyreRequest(String targetURL, String requestBody, String method, String apiKey, String secretKey) {
URL url;
HttpURLConnection connection = null;
try {
targetURL += ((targetURL.indexOf("?")>0)?"&":"?") + "timestamp=" + System.currentTimeMillis();
//Create connection
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod(method);
System.out.println(connection.getRequestMethod());
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Content-Length", Integer.toString(requestBody.getBytes().length));
//Specify API v2
connection.setRequestProperty("X-Api-Version","2");
// Provide API key and signature
connection.setRequestProperty("X-Api-Key", apiKey);
connection.setRequestProperty("X-Api-Signature",computeSignature(secretKey,targetURL,requestBody));
//Send request
if(method.equals("POST")) {
connection.setDoOutput(true);
connection.setRequestMethod(method);
DataOutputStream wr = new DataOutputStream(
connection.getOutputStream());
wr.write(requestBody.getBytes("UTF-8"));
wr.flush();
wr.close();
}
//Get Response
InputStream is;
if (connection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
is = connection.getInputStream();
} else {
is = connection.getErrorStream();
}
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if(connection != null) {
connection.disconnect();
}
}
}
public static String computeSignature(String secretKey, String url, String reqData) {
String data = url + reqData;
System.out.println(data);
try {
Mac sha256Hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
sha256Hmac.init(key);
byte[] macData = sha256Hmac.doFinal(data.getBytes("UTF-8"));
String result = "";
for (final byte element : macData){
result += Integer.toString((element & 0xff) + 0x100, 16).substring(1);
}
return result;
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
require 'uri'
require 'net/http'
require 'digest/hmac'
require 'json'
class WyreApi
ACCOUNT_ID = 'ue5hsnusf8gene87asdf4es23bt9d7ak'
API_KEY = '9idihi38o18mrm1234ipa1k9ooiifgts'
SEC_KEY = '5e3kcoogptge6s5fh2qwertyb6g368dm'
API_URL = 'https://api.sendwyre.com'
def create_transfer options
api_post '/transfers', options
end
private
def api_post path, post_data = {}
params = {
'timestamp' => (Time.now.to_i * 1000).to_s
}
url = API_URL + path + '?' + URI.encode_www_form(params)
headers = {
'X-Api-Key' => API_KEY,
'X-Api-Signature' => calc_auth_sig_hash(url + post_data.to_json.to_s),
'X-Api-Version' => '2'
}
uri = URI API_URL
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
http.request_post(url, post_data.to_json.to_s, headers) do |res|
response = JSON.parse res.body
raise response['message'] if res.code != '200'
return response
end
end
end
def calc_auth_sig_hash url_body
return Digest::HMAC.hexdigest url_body, SEC_KEY, Digest::SHA256
end
end
api = WyreApi.new
api.create_transfer({'sourceAmount'=>50,'sourceCurrency'=>'USD','dest'=>'[email protected]', 'destCurrency'=>'EUR', 'message'=>'buy sam pizza')
#dependencies:
#python3
#pip3 install requests
import json
import hmac
import time
from requests import request
class MassPay_API(object):
def __init__(self, account_id, api_version, api_key, api_secret):
self.account_id = account_id
self.api_url = 'https://api.sendwyre.com/{}'.format(api_version)
self.api_version = api_version
self.api_key = api_key
self.api_secret = api_secret
#authentication decorator. May raise ValueError if no json content is returned
def authenticate_request(func):
def wrap(self, *args, **kwargs):
url, method, body = func(self, *args, **kwargs)
params = {}
timestamp = int(time.time() * 1000)
url += '?timestamp={}'.format(timestamp)
bodyJson = json.dumps(body) if body != '' else ''
headers = {}
headers['Content-Type'] = 'application/json'
headers['X-Api-Version'] = self.api_version
headers['X-Api-Key'] = self.api_key
headers['X-Api-Signature'] = hmac.new(self.api_secret.encode('utf-8'), (url + bodyJson).encode('utf-8'), 'SHA256').hexdigest()
print(headers['X-Api-Signature'])
resp = request(method=method, url=url, params=params, data=(json.dumps(body) if body != '' else None), json=None, headers=headers)
if resp.text is not None: #Wyre will always try to give an err body
return resp.status_code, resp.json()
return 404, {}
return wrap
@authenticate_request
def retrieve_exchange_rates(self):
url = self.api_url + '/rates'
method = 'GET'
body = ''
return url, method, body
@authenticate_request
def retrieve_account(self):
url = self.api_url + '/account'
method = 'GET'
body = ''
return url, method, body
@authenticate_request
def create_transfer(self, sourceAmount, sourceCurrency, destAmount, destCurrency, destAddress, message, autoConfirm):
url = self.api_url + '/transfers'
method = 'POST'
#ONLY use either sourceAmount or destAmount, see documentation
body = {'sourceCurrency':sourceCurrency,
'dest':destAddress,
'destCurrency':destCurrency,
'message':message}
if sourceAmount:
body["sourceAmount"] = sourceAmount
elif destAmount:
body["destAmount"] = destAmount
if autoConfirm:
body['autoConfirm'] = True
return url, method, body
@authenticate_request
def confirm_transfer(self, transfer_id):
url = self.api_url + '/transfer/{}/confirm'.format(transfer_id)
method = 'POST'
body = ''
return url, method, body
@authenticate_request
def status_transfer(self, transfer_id):
url = self.api_url + '/transfer/{}'.format(transfer_id)
method = 'GET'
body = ''
return url, method, body
#USAGE Example
account_id = "YOUR_ACCOUNT_ID_HERE" #optional
api_key = "YOUR_API_KEY_HERE"
secret_key = "YOUR_SECRET_KEY_HERE"
api_version = "2"
#create Wyre API object
Wyre = Pay_API(account_id, api_version, api_key, secret_key)
#get account info
http_code, account = Wyre.retrieve_account()
print(account)
#get exchange rate info
http_code, rate_result = Wyre.retrieve_exchange_rates()
print(rate_result)
#BTC to CNY rate
btc_cny = rate_result.get("BTCCNY")
#amount of source (withdrawal) BTC we want to sent to Euro
amount = 50
#calculate destination (deposit) amount in CNY
final_amount = amount * btc_cny
#example bank transfer
bank_transfer = {
"paymentMethodType":"INTERNATIONAL_TRANSFER",
"country": "CN",
"currency": "CNY",
"nameOnAccount": "ζιΎ",
"accountNumber": "1234dinosaur",
"bankName": "ζειΆθ‘",
"accountType": "ιε‘",
"branchCode": "ε
εθ·―ζ―θ‘",
"accountHolderEmail": "[email protected]",
"accountHolderPhoneNumber": "+14102239203",
"swift": "DEUTUS00000",
"beneficiaryType": "INDIVIDUAL",
"priority":"HIGH"
}
#don't actually run this unless you really want to give Sam pizza
http_code, transfer_result = Wyre.create_transfer(
amount,
"BTC",
None, #final_amount
"CNY",
bank_transfer, #may also be an email or SRN
"sending Wyre developers pizza money",
False)
print(transfer_result)
tx_id = transfer_result['id']
http_code, status = Wyre.status_transfer('AWEvg0lZhq6qpXX')
print(status)