0

Back again. I have successfully learned how to sign my GET requests for the E*TRADE API, but now I am up to POST requests for placing orders.

I build the order and use a REST POST to send the request.

The string to encode for the signature is the same as what I am using for GET of my account information and market data, except instead of "GET" at the start is replaced by "POST".

The string to encode for the signature is:

POST&%20https%3A%2F%2Fapi.etrade.com%2Fv1%2Faccounts%2F{accountkeyredacted}%2Forders%2Fpreview&oauth_consumer_key%3D{keyredacted}3%26oauth_nonce%3D762480b2bdbae095aff70d8c2da908ab%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1691173914%26oauth_token%3D{tokenredacted}%253D

In addition to setting the Authorization header I set the Content-Type header to appllication/xml

I tried adding "Content-Type=application/xml" to the base string for the signature.

From another similar question I saw something about oauth_body_hash="". Do I need to hash the entire xml body of the order? If so how to you add the entire body of the request to the signature.

I tried showing code but I couldn't post it because of an error saying I had too much code.

I have tried to add oauth_body_hash. In the POST I use with TDAmeritrade (and with E*Trade) I am posting a stream. So I use the same stream to create the body to hash.

var
  bodyText: string;
  DataStream: TMemoryStream;
begin
  DataStream := TMemoryStream.Create;
  try
    Body.SaveToStream(DataStream);
    DataStream.Seek(0, 0);
    bodyText := ReadStreamAsString(DataStream);
  finally
    DataStream.Free;
  end;
  FKey := URIEncode(etrade_consumer_secret) + '&';
  if AccessSecret <> '' then
    FKey := FKey + URIEncode(AccessSecret)
  else if TokenSecret <> '' then
    FKey := FKey + URIEncode(TokenSecret);
  OutputDebugString(FKey);
  FBodySignature := TNetEncoding.Base64.EncodeBytesToString(THashSHA1.GetHMACAsBytes(bodyText, FKey));

and I add it to the base string that I hash

    if FBodySignature <> '' then
      Data.Add('oauth_body_hash=' + URIEncode(FBodySignature));

and to the header

    result := format('oauth_signature="%s",' +
                     'oauth_nonce="%s",' +
                     'oauth_body_hash="%s",' +
                     'oauth_signature_method="HMAC-SHA1",' +
                     'oauth_consumer_key="%s",' +
                     'oauth_timestamp="%s",' +
                     'oauth_token="%s"',
            [SignatureEncoded, Nonce, UriEncode(FbodySignature), UriEncode(ConsumerKey), Timestamp, URIEncode(Token)]);

Still signature invalid.

I tried adding the oauth_body_hash just to the header but not to the main signature. Doesn't work either.

I looked at the python example and it has the following headers:

        # Add parameters and header information
        headers = {"Content-Type": "application/xml", "consumerKey": config["DEFAULT"]["CONSUMER_KEY"]}

I added my consumerKey as a header. No difference.

0 Answers0