Search code examples
python

Error 405 when trying create withdrawal order with okx api


I'm trying create a order of withdrawal, but the response alerts error 405. I read the docs and saw that this error is related of wrong method, but I'm sure that the correct is POST The documentation is: https://www.okx.com/docs-v5/en/?typescript#spread-trading-websocket-private-channel-trades-channel The create-withdrawal-order: https://www.okx.com/docs-v5/en/?python#funding-account-rest-api-create-withdrawal-order

The code that I'm using:

import json, requests
import base64, hmac
from datetime import datetime, timezone
import hashlib
import random
import string

class OkxAPI:
    def __init__(self, APIKEY: str, APISECRET: str, PASS: str):
        self.apikey = APIKEY
        self.apisecret = APISECRET
        self.password = PASS
        self.baseURL = 'https://okx.com'

    @staticmethod
    def get_time():
        timestamp = datetime.now(timezone.utc).isoformat(timespec='milliseconds').replace("+00:00", "Z")
        return timestamp

    @staticmethod
    def create_client_id(length = 32):
      characters = string.ascii_lowercase + string.digits
      return ''.join(random.choices(characters, k=length))

    def signature(self, timestamp, method, request_path, body, secret_key):
        message = timestamp + method + request_path + body
        signature = hmac.new(
          self.apisecret.encode(), message.encode(), hashlib.sha256
        ).digest()
        output = base64.b64encode(signature).decode()
        return output

    def get_header(self, request='GET', endpoint='', body=''):
        cur_time = self.get_time()
        header = dict()
        header['CONTENT-TYPE'] = "application/json"
        header['OK-ACCESS-KEY'] = self.apikey
        header['OK-ACCESS-SIGN'] = self.signature(cur_time, request, endpoint, body, self.apisecret)
        header['OK-ACCESS-TIMESTAMP'] = cur_time
        header['OK-ACCESS-PASSPHRASE'] = self.password
        return header

    def withdrawal_payment_methods(self, ccy):
      endpoint = f'/api/v5/fiat/withdrawal-payment-methods?ccy={ccy}'
      url = self.baseURL + endpoint
      # body = {
      #     'ccy': ccy
      # }
      request = 'GET'
      header = self.get_header(request, endpoint)
      print(header)
      response = requests.get(url, headers = header)
      return response.json()

    def create_withdrawal(self, ccy, amount):
      clientId = self.create_client_id()
      endpoint = f'/api/v5/fiat/create-withdrawal'
      body = f"?paymentAcctId=my-account?ccy={ccy}?amt={amount}?paymentMethod=PIX?clientId={clientId}"
      url = self.baseURL + endpoint
      request = 'POST'
      header = self.get_header(request, endpoint, body)
      print(header)
      response = requests.post(url, endpoint)
      return response.json()

apiKey = ''
secretKey = ''
passphrase = ''
okx = OkxAPI(apiKey, secretKey, passphrase)
# print(okx.withdrawal_payment_methods('BRL'))
print(okx.create_withdrawal('BRL', '10'))

I tried change the method, but the error persists. I'm also implement another method, withdrawal_payment_method, and it works, so I think that signature/get_time are ok.


Solution

  • Based on furas answer,I discovered that not only body must be included, but also the parameters. So the create_withdrawal must be implemented like this:
    
    def create_withdrawal(self, ccy, amount):
      clientId = self.create_client_id()
      endpoint = f'/api/v5/fiat/create-withdrawal?paymentAcctId=my-account?ccy={ccy}?amt={amount}?paymentMethod=PIX?clientId={clientId}'
      body = {
          "paymentAcctId": "my-account",
          "ccy": ccy,
          "amt": amount,
          "paymentMethod": "PIX",
          "clientId": clientId,
      }
      url = self.baseURL + endpoint
      request = 'POST'
      header = self.get_header(request, endpoint, body = json.dumps(body))
      response = requests.post(url, headers = header, data = json.dumps(body))
      return response.json()