{"metadata":{"image":[],"title":"","description":""},"api":{"url":"","auth":"required","params":[],"results":{"codes":[]},"settings":""},"next":{"description":"","pages":[]},"title":"HMAC Authentication","type":"basic","slug":"hmac","excerpt":"","body":"HMAC Authentication can be used for authentication through the coins.ph API using the developer's account. \n\nIf you are building a client side application, we recommend using [OAuth2](doc:oauth) instead. This is because HMAC requires you to use your API secret to sign requests, which you should store in a medium that you control, such as your own server.\n\nYou can get your API Key and secret by selecting your application and clicking \"show\" from the [API Access Dashboard](https://app.coins.ph/app/dashboard/oauth2-apps).\n\n## Signing a request\n\nEach request made with [HMAC](https://en.wikipedia.org/wiki/HMAC) authentication needs to be signed. To calculate a signature you will need:\n\n 1. API key found in API Access Dashboard\n 2. Construct a message according to the following pseudo-grammar: `NONCE + URL + BODY`\n 3. Calculate an HMAC with the message string you just created, your API secret as the key, and SHA256 as the hash algorithm.\n\nThe code below demonstrates how to create a proper signature.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"import time\\nimport hashlib\\nimport hmac\\nimport requests\\n\\n# Coins.ph base API url\\n# Replace with 'https://api.coins.asia' for production system\\nBASE_URL = 'https://api.coins.asia.stage.coins.systems'\\n\\n# Coins.ph API key\\nAPI_KEY = ''\\nAPI_SECRET = ''\\n\\nurl = BASE_URL + '/v1/sellorder'\\nnonce = str(int(time.time() * 1e6))\\n\\n# for GET requests body would be empty ''\\nbody = '{\\\"outlet_id\\\": \\\"test_outlet_1\\\"}'\\n\\nkey = API_KEY\\nmessage = nonce + url + body\\nsecret = API_SECRET\\n\\nsignature = hmac.new(\\n  secret.encode('ascii'),\\n  message.encode(),\\n  hashlib.sha256,\\n).hexdigest()\\n\\nheaders = {\\n    'Access-Signature': signature,\\n    'Access-Key': key,\\n    'Access-Nonce': nonce,\\n    'Content-Type': 'application/json',\\n    'Accept': 'application/json'\\n}\\n\\nresponse = requests.post(url, headers=headers, data=body)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"String nonce = String.valueOf(System.currentTimeMillis());\\nString message = nonce + url + (body != null ? body : \\\"\\\");\\n\\nMac mac = Mac.getInstance(\\\"HmacSHA256\\\");\\nmac.init(new SecretKeySpec(API_SECRET.getBytes(), \\\"HmacSHA256\\\"));\\nString signature = new String(Hex.encodeHex(mac.doFinal(message.getBytes())));\\nrequest.setHeader(\\\"ACCESS_KEY\\\", API_KEY);\\nrequest.setHeader(\\\"ACCESS_SIGNATURE\\\", signature);\\nrequest.setHeader(\\\"ACCESS_NONCE\\\", nonce);\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\nFor an example of how to use this function for an HMAC request, please see the [Send funds to an email/phone number](doc:transfer-funds-api-tutorial) tutorial.\n\n## Troubleshooting\n\n### How to prepare the message?\n\nThe message is a result of concatenating the nonce, the URL, and the body. On the other hand, if the body is empty, the message is a result of the concatenation of the nonce and the URL.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Given the following values:\\nurl = 'https://api.coins.asia.stage.coins.systems/v3/partner-payout-outlet-fees'\\nnonce = '1591094811411138'\\nbody = '{\\\"outlet_id\\\":\\\"test_outlet_1\\\"}'\\n\\n# The message is as follows:\\nmessage = nonce + url + body\\n\\n# Which results to:\\n# 1591094811411138https://api.coins.asia.stage.coins.systems/v3/partner-payout-outlet-fees{\\\"outlet_id\\\":\\\"test_outlet_1\\\"}\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\n### How to calculate a signature?\n\nHMAC signature calculation should be available as a library in most popular languages. To do the calculation, it requires a secret, a message and a hash function (in Coins.ph, SHA256 is used).\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Given the following values:\\nsecret = 'ivjtwoYrjPn9NDaSCntGtPfl5BpZ5qD9Mp4WSViDaam7SwU4wV'\\nmessage = '1591094811411138https://api.coins.asia.stage.coins.systems/v3/partner-payout-outlet-fees{\\\"outlet_id\\\":\\\"test_outlet_1\\\"}'\\n\\n# When calculating the signature:\\nHMAC(message, secret, 'sha256')\\n\\n# The expected signature should be:\\n# 89b2922a3aea58026fa4b97381ea8e29a4fb3594ecce6e4d02c98fee7a3066da\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\n### I'm still getting HTTP 401 Unauthorized with \"Unable to match Access-Signature.\" error.\n\nIf you're signature is still not matching, please double check the following:\n\n1. Make sure the message is constructed properly.\n2. Make sure the signature is calculated correctly.\n3. Make sure HTTP request nonce that's used in the message is the same as in the headers.\n4. Make sure HTTP request body used in the message is the same as the body sent to Coins.ph API gateway.\n5. Make sure your using the correct pair of `API_KEY` and `API_SECRET`.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Some libraries allows to specify the HTTP body as a raw string (or byte array) and also as an object. When an object is passed, it is then serialized into raw byte array and its serialization might differ from what was used during the signature calculation.\",\n  \"title\": \"Request Body Gotcha\"\n}\n[/block]\n## Making Requests\n\nEach HMAC requests expect the following HTTP Headers:\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Header Name\",\n    \"h-1\": \"Description\",\n    \"0-0\": \"`ACCESS_KEY`\",\n    \"1-0\": \"`ACCESS_SIGNATURE`\",\n    \"2-0\": \"`ACCESS_NONCE`\",\n    \"0-1\": \"Select `show` on your chosen application's [API Access](https://app.coins.ph/app/dashboard/oauth2-apps) dashboard. This is the API Key as displayed on the dialog.\",\n    \"1-1\": \"An HMAC-SHA256 hash of the nonce concatenated with the full URL and body of the HTTP request, signed using your API secret.\",\n    \"2-1\": \"A number that can only be used once per user.\"\n  },\n  \"cols\": 2,\n  \"rows\": 3\n}\n[/block]\nAdditional headers may be required depending on the API call you are making. For instance, POST requests require the header `Content-Type: application/json`, while GET requests do not expect this header.\n\n## Use a Nonce\n\nA [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) is used to prevent replay-attacks. Every API call requires a nonce. We expect the nonce to always increase for every request from the same user. The simplest form of nonce you can use is a Unix Epoch timestamp, but feel free to use other forms.\n\n### Nonces and Parallel Requests\n\nSince our service is expecting the nonce to increase for every subsequent request, this limits the possibility of executing parallel requests with our API. For instance, consider two requests sent out simultaneously. One request has a higher nonce than the other. If that request is accepted before the one with a lower nonce, the request with the lower nonce will not be accepted. Until this issue is solved, we do not recommend sending parallel requests with HMAC.\n\n## Storing Credentials Securely\n\nAlways make sure your API Credentials are stored securely, Your `api_key`, `api_secret`, and access tokens may be used to access and perform actions in your coins account. In particular, you should avoid storing credentials in your code base and code repositories (like github).\n\n**Coins will never ask for your API secret. There is no need to include the API secret on a request.** \n\nIf there's a need for you to store your secret in a device you don't control (say, a mobile device), it is completely your responsibility to protect the secret. We recommend using encryption and using obfuscation to protect your application from disassemblers and reverse-engineering. Please refer to your chosen platform's documentation for more information.","updates":["5981c9d8302822002abfc7a6","5de0ff3489a40c0011f1654d","5ed63134e2cc1f004ffb641a"],"order":1,"isReference":false,"hidden":false,"sync_unique":"","link_url":"","link_external":false,"_id":"56326ea3df556c0d00cd08f7","category":{"sync":{"isSync":false,"url":""},"pages":["56326ea3df556c0d00cd08f6","56326ea3df556c0d00cd08f7","56326ea3df556c0d00cd08f8"],"title":"Authentication","slug":"authentication","order":1,"from_sync":false,"reference":false,"_id":"56326e9ddf556c0d00cd08cc","__v":1,"project":"544fc17e698ab40800b4f891","version":"56326e9cdf556c0d00cd08ca","createdAt":"2015-05-01T05:42:46.293Z"},"user":"544fc065698ab40800b4f888","project":"544fc17e698ab40800b4f891","parentDoc":null,"__v":3,"createdAt":"2015-05-01T07:58:38.852Z","githubsync":"","version":{"version":"2.1","version_clean":"2.1.0","codename":"collector","is_stable":true,"is_beta":false,"is_hidden":false,"is_deprecated":false,"categories":["56326e9ddf556c0d00cd08cb","56326e9ddf556c0d00cd08cc","56326e9ddf556c0d00cd08cd","56326e9ddf556c0d00cd08ce","56326e9ddf556c0d00cd08cf","56326e9ddf556c0d00cd08d0","56326e9ddf556c0d00cd08d1","56326e9ddf556c0d00cd08d2","56326e9ddf556c0d00cd08d3","56326e9ddf556c0d00cd08d4","56d942ac337fd11300d6a251","5ab2fcf66a1d77001230b47e","5afc2943bd2ef4000330bca7","5d1d87419a969a00141c6b4c","5d1d8948ef26b2002c6468d1","5d1d8afe7b2b24005bec7de0","5d1d8b24f5cfcb00201490bb","5d1d8bb82d46d1004a02581f","5d1d8de1e4edb0019ed63acd","5d1d8f6b613fb90050d0d3e0","5d1d934ed377870191039d28","5d1d99810b2e4600500eb5ff","5d1da14e613fb90050d0d491","5d229a846cf323005a7fa998","5d229a8c8abf65001cc4768d","5d229a9494b856002e26b6e1","5d229a9bf77bb900507ccb04","5d229aa88abf65001cc4768e","5d24310a9ca8c80054786177","5d24359101cc3a00508e7482","5d24418fa791b20050733b32"],"_id":"56326e9cdf556c0d00cd08ca","project":"544fc17e698ab40800b4f891","releaseDate":"2015-10-29T19:08:12.724Z","__v":22,"createdAt":"2015-10-29T19:08:12.724Z"},"updatedAt":"2019-07-04T07:56:23.193Z"}

HMAC Authentication


HMAC Authentication can be used for authentication through the coins.ph API using the developer's account. If you are building a client side application, we recommend using [OAuth2](doc:oauth) instead. This is because HMAC requires you to use your API secret to sign requests, which you should store in a medium that you control, such as your own server. You can get your API Key and secret by selecting your application and clicking "show" from the [API Access Dashboard](https://app.coins.ph/app/dashboard/oauth2-apps). ## Signing a request Each request made with [HMAC](https://en.wikipedia.org/wiki/HMAC) authentication needs to be signed. To calculate a signature you will need: 1. API key found in API Access Dashboard 2. Construct a message according to the following pseudo-grammar: `NONCE + URL + BODY` 3. Calculate an HMAC with the message string you just created, your API secret as the key, and SHA256 as the hash algorithm. The code below demonstrates how to create a proper signature. [block:code] { "codes": [ { "code": "import time\nimport hashlib\nimport hmac\nimport requests\n\n# Coins.ph base API url\n# Replace with 'https://api.coins.asia' for production system\nBASE_URL = 'https://api.coins.asia.stage.coins.systems'\n\n# Coins.ph API key\nAPI_KEY = ''\nAPI_SECRET = ''\n\nurl = BASE_URL + '/v1/sellorder'\nnonce = str(int(time.time() * 1e6))\n\n# for GET requests body would be empty ''\nbody = '{\"outlet_id\": \"test_outlet_1\"}'\n\nkey = API_KEY\nmessage = nonce + url + body\nsecret = API_SECRET\n\nsignature = hmac.new(\n secret.encode('ascii'),\n message.encode(),\n hashlib.sha256,\n).hexdigest()\n\nheaders = {\n 'Access-Signature': signature,\n 'Access-Key': key,\n 'Access-Nonce': nonce,\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n}\n\nresponse = requests.post(url, headers=headers, data=body)", "language": "python" }, { "code": "String nonce = String.valueOf(System.currentTimeMillis());\nString message = nonce + url + (body != null ? body : \"\");\n\nMac mac = Mac.getInstance(\"HmacSHA256\");\nmac.init(new SecretKeySpec(API_SECRET.getBytes(), \"HmacSHA256\"));\nString signature = new String(Hex.encodeHex(mac.doFinal(message.getBytes())));\nrequest.setHeader(\"ACCESS_KEY\", API_KEY);\nrequest.setHeader(\"ACCESS_SIGNATURE\", signature);\nrequest.setHeader(\"ACCESS_NONCE\", nonce);", "language": "java" } ] } [/block] For an example of how to use this function for an HMAC request, please see the [Send funds to an email/phone number](doc:transfer-funds-api-tutorial) tutorial. ## Troubleshooting ### How to prepare the message? The message is a result of concatenating the nonce, the URL, and the body. On the other hand, if the body is empty, the message is a result of the concatenation of the nonce and the URL. [block:code] { "codes": [ { "code": "# Given the following values:\nurl = 'https://api.coins.asia.stage.coins.systems/v3/partner-payout-outlet-fees'\nnonce = '1591094811411138'\nbody = '{\"outlet_id\":\"test_outlet_1\"}'\n\n# The message is as follows:\nmessage = nonce + url + body\n\n# Which results to:\n# 1591094811411138https://api.coins.asia.stage.coins.systems/v3/partner-payout-outlet-fees{\"outlet_id\":\"test_outlet_1\"}", "language": "text" } ] } [/block] ### How to calculate a signature? HMAC signature calculation should be available as a library in most popular languages. To do the calculation, it requires a secret, a message and a hash function (in Coins.ph, SHA256 is used). [block:code] { "codes": [ { "code": "# Given the following values:\nsecret = 'ivjtwoYrjPn9NDaSCntGtPfl5BpZ5qD9Mp4WSViDaam7SwU4wV'\nmessage = '1591094811411138https://api.coins.asia.stage.coins.systems/v3/partner-payout-outlet-fees{\"outlet_id\":\"test_outlet_1\"}'\n\n# When calculating the signature:\nHMAC(message, secret, 'sha256')\n\n# The expected signature should be:\n# 89b2922a3aea58026fa4b97381ea8e29a4fb3594ecce6e4d02c98fee7a3066da", "language": "text" } ] } [/block] ### I'm still getting HTTP 401 Unauthorized with "Unable to match Access-Signature." error. If you're signature is still not matching, please double check the following: 1. Make sure the message is constructed properly. 2. Make sure the signature is calculated correctly. 3. Make sure HTTP request nonce that's used in the message is the same as in the headers. 4. Make sure HTTP request body used in the message is the same as the body sent to Coins.ph API gateway. 5. Make sure your using the correct pair of `API_KEY` and `API_SECRET`. [block:callout] { "type": "info", "body": "Some libraries allows to specify the HTTP body as a raw string (or byte array) and also as an object. When an object is passed, it is then serialized into raw byte array and its serialization might differ from what was used during the signature calculation.", "title": "Request Body Gotcha" } [/block] ## Making Requests Each HMAC requests expect the following HTTP Headers: [block:parameters] { "data": { "h-0": "Header Name", "h-1": "Description", "0-0": "`ACCESS_KEY`", "1-0": "`ACCESS_SIGNATURE`", "2-0": "`ACCESS_NONCE`", "0-1": "Select `show` on your chosen application's [API Access](https://app.coins.ph/app/dashboard/oauth2-apps) dashboard. This is the API Key as displayed on the dialog.", "1-1": "An HMAC-SHA256 hash of the nonce concatenated with the full URL and body of the HTTP request, signed using your API secret.", "2-1": "A number that can only be used once per user." }, "cols": 2, "rows": 3 } [/block] Additional headers may be required depending on the API call you are making. For instance, POST requests require the header `Content-Type: application/json`, while GET requests do not expect this header. ## Use a Nonce A [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) is used to prevent replay-attacks. Every API call requires a nonce. We expect the nonce to always increase for every request from the same user. The simplest form of nonce you can use is a Unix Epoch timestamp, but feel free to use other forms. ### Nonces and Parallel Requests Since our service is expecting the nonce to increase for every subsequent request, this limits the possibility of executing parallel requests with our API. For instance, consider two requests sent out simultaneously. One request has a higher nonce than the other. If that request is accepted before the one with a lower nonce, the request with the lower nonce will not be accepted. Until this issue is solved, we do not recommend sending parallel requests with HMAC. ## Storing Credentials Securely Always make sure your API Credentials are stored securely, Your `api_key`, `api_secret`, and access tokens may be used to access and perform actions in your coins account. In particular, you should avoid storing credentials in your code base and code repositories (like github). **Coins will never ask for your API secret. There is no need to include the API secret on a request.** If there's a need for you to store your secret in a device you don't control (say, a mobile device), it is completely your responsibility to protect the secret. We recommend using encryption and using obfuscation to protect your application from disassemblers and reverse-engineering. Please refer to your chosen platform's documentation for more information.