title: How to create HTTP Header for eBay Browse API Function
body: <p>I am trying to get a Product Review Rating through eBay's Browse API. Here is my code for this function:</p>
  
  <pre class="lang-pascal prettyprint-override"><code>sHeaders := TStringList.Create;
  sHeaders.Add('X-EBAY-C-ENDUSERCTX=' + '"affiliateCampaignId=' + '533xxxxxxx"');
  objIdHTTP.Request.CustomHeaders.AddStdValues(sHeaders);
  sResponse := objIdHTTP.Get('https://api.sandbox.ebay.com/buy/browse/v1/item/v1|123456789|0');
  </code></pre>
  
  <p>But I get a Socket Error 10054 when I test this code.</p>
  
  <p>It might be something wrong with the customer header part, but I can't figure out how to make it work.</p>
  
  <p>Could anyone please help me with any mistakes?</p>
  
  <p>Here is a link to eBay's API document that I am referring to:</p>
  
  <p><a href="https://developer.ebay.com/api-docs/buy/static/api-browse.html#Headers" rel="nofollow noreferrer">Browse API | Use request headers</a></p>
  
  <p><strong>UPDATE</strong>: here is my updated code:</p>
  
  <pre class="lang-pascal prettyprint-override"><code>objIdHTTP.Request.CustomHeaders.AddValue('X-EBAY-C-ENDUSERCTX', 'affiliateCampaignId=' + '533xxxxxxx');
  sResponse := objIdHTTP.Get('https://api.sandbox.ebay.com/buy/browse/v1/item/v1|123456789|0');
  </code></pre>
  
  <p>It still has the same error.</p>
  
  <p>I tested the URL link in Postman, and I got an error message as below:</p>
  
  <pre><code>{
    "errors": [
        {
          "errorId": 1002,
          "domain": "OAuth",
          "category": "REQUEST",
          "message": "Missing access token",
          "longMessage": "Access token is missing in the Authorization HTTP request header."
        }
    ]
  }
  </code></pre>
  
  <p>Many IDs exist, such as AppID, DevID, CerID, OAuthToken (9583 characters), Token for Store (3343 characters), EPN Campaign (already included in this URL header).</p>
  
  <p>I tried with <code>X-EBAY-API-IAF-TOKEN: OAuthToken</code>, but it replied with the same error message.</p>
  
  <p><strong>UPDATE</strong>: </p>
  
  <p>Thanks for all help in StackOverflow, specailly Remy Lebeau. Finally I got working codes as below:</p>
  
  <pre><code>with objHTTP.Request.CustomHeaders do begin
    Clear;
    FoldLines := False;
    Values['Content-Type'] := 'application/x-www-form-urlencoded';
    Values['Authorization'] := 'Basic ' + 'myAuthCode';
  end;
  xRequestBody := TStringStream.Create('{"Authorization":"Basic ' + 'myAuthCode' + '"' + ','
                                     + ' "Content-Type:' + 'application/x-www-form-urlencoded' + '"}',
                                       TEncoding.UTF8);
  
  sResponse := objHTTP.Post(sURL, xRequestBody);
  </code></pre>
  
  <p>I still have no idea why indy HTTP needs to assign ContentType and Authorization twice but these codes work well for me now.</p>
  
  <p><strong>UPDATE</strong>: Refer to advice from Remy Lebeau, ContentType is assigned to idHTTP.Request directly and codes are updated again as below:</p>
  
  <pre><code>with objHTTP.Request do begin
    Clear;
    ContentType := 'application/x-www-form-urlencoded';
    CustomHeaders.FoldLines := False;
    CustomHeaders.Values['Authorization'] := 'Basic ' + myAuthCode;
  end;
  xRequestBody := TStringStream.Create('{"Authorization":"Basic ' + myAuthCode + '"}', TEncoding.UTF8);
  
  sResponse := objHTTP.Post(sURL, xRequestBody);
  </code></pre>
  
  <p>Let's go back to my start point. Now I start to struggle with GET to have Authorization, code is modified from first part to those (code is updated again in order to capture http request):</p>
  
  <pre><code>objHTTP.Intercept := xIdLogDebug;
  with objHTTP.Request.CustomHeaders do begin
    Clear;
    FoldLines := False;
    Values['X-EBAY-C-ENDUSERCTX'] := 'affiliateCampaignId=' + '533xxxxxxx';
    Values['Authorization'] := 'Bearer ' + myToken;
    Values['Postman-Token'] := '65546b71-aef8-422e-916d-93b75ddd9de2,a0687ba7-e142-4849-8288-a8f89b66f253';
    Accept := '*/*';
    UserAgent := 'PostmanRuntime/7.13.0';
    CacheControl := 'no-cache';
    AcceptEncoding := 'gzip, deflate';
    Connection := 'keep-alive';
  end;
  
  with objHTTP do begin
    AllowCookies := True;
    CookieManager  := objCookie;
  end;
  
  Result := objHTTP.Get('https://api.sandbox.ebay.com/buy/browse/v1/item/v1|123456789|0');
  </code></pre>
  
  <p>It still gets Socket Error 10054. I tested this URL in Postman and it works fine. The only different I can point out is that there is one TYPE option for Authorization inside Postman, and it is selected as "OAuth 2.0".</p>
  
  <p>So, how to assign authorization to Indy HTTP for GET? Might be something like RequestBody in POST.</p>
  
  <p><strong>UPDATE</strong>:</p>
  
  <p>Here is received data by POST call through IndyHTTP:</p>
  
  <pre><code>HTTP/1.1 200 OK
  Content-Length: 1905
  Date: Sat, 01 Jun 2019 11:09:08 GMT
  RlogId: t6ldssk%28ciudbq%60anng%7Fu2h%3F%3Cwk%7Difvqn*14%3F0512%29pqtfwpu%29pdhcaj%7E%29fgg%7E%606%28dlh-16b12ba9d25-0x4fd7e
  Set-Cookie: ebay=%5Esbf%3D%23%5E;Domain=.ebay.com;Path=/
  Set-Cookie: dp1=bu1p/QEBfX0BAX19AQA**5ed39054^;Domain=.ebay.com;Expires=Mon, 31-May-2021 11:09:08 GMT;Path=/
  X-Content-Type-Options: nosniff
  X-EBAY-C-VERSION: 1.0.0
  X-EBAY-REQUEST-ID: 16b12ba9d1f.a0962ac.25e7e.ff9d75b3!/identity/v1/oauth2/!10.9.98.172!esbnewesbngcos[]!token.clientcredentials!10.9.107.144!r1oauth-envadvcdhidzs5k[IdentityCDSClient[!ClientDetailResourceV1.getClientDetail!10.199.16.86!r1oauthclnt-envjiwv5gtvevlbi[]]]
  X-Frame-Options: SAMEORIGIN
  X-XSS-Protection: 1; mode=block
  Content-Type: application/json
  Connection: keep-alive
  
  {"access_token":"v^1.1#i^............","expires_in":7200,"token_type":"Application Access Token"}
  </code></pre>
  
  <p>This is captured request by GET call (run after POST) from IndyHTTP (converted from TIdBytes to String):</p>
  
  <pre><code>GET /buy/browse/v1/item/v1|123456789|0 HTTP/1.1
  Content-Type: application/json
  X-EBAY-C-ENDUSERCTX: affiliateCampaignId=533xxxxxxx
  Authorization: Bearer v^1.1#i^............
  Postman-Token: 65546b71-aef8-422e-916d-93b75ddd9de2,a0687ba7-e142-4849-8288-a8f89b66f253
  Host: api.sandbox.ebay.com
  Accept: */*
  Accept-Encoding: gzip, deflate, identity
  User-Agent: PostmanRuntime/7.13.0
  Cookie: dp1=bu1p/QEBfX0BAX19AQA**5ed3395b^; ebay=%5Esbf%3D%23%5E
  </code></pre>
  
  <p>And this is code copied from Postman:</p>
  
  <pre><code>GET /buy/browse/v1/item/v1|123456789|0 HTTP/1.1
  Host: api.sandbox.ebay.com
  X-EBAY-C-ENDUSERCTX: affiliateCampaignId=533xxxxxxx
  Authorization: Bearer v^1.1#i^............
  User-Agent: PostmanRuntime/7.13.0
  Accept: */*
  Cache-Control: no-cache
  Postman-Token: 65546b71-aef8-422e-916d-93b75ddd9de2,a0687ba7-e142-4849-8288-a8f89b66f253
  Host: api.sandbox.ebay.com
  cookie: ebay=%5Esbf%3D%23%5E; dp1=bu1p/QEBfX0BAX19AQA**5ed2398a^bl/AU60b36d0a^; s=; nonsession=CgADKACBmVweKZWYwZThjOGQxNmEwYWMxZTQ2MDNlNGJhZmZkYjQzNTT+86sJ
  accept-encoding: gzip, deflate
  Connection: keep-alive
  cache-control: no-cache
  </code></pre>
  
  <p>I am struggling which parameter makes IndyHTTP got #10054 error from server.</p>
  
  <p>Thanks.</p>