Do's and Don'ts: Security and authentication
All communication with the Tango API must be authenticated. The API authentication process validates the identity of the user attempting to connect to the server. The authentication protocol sends credentials from the remote user requesting access to the server. For an authentication account, reach out to one of our Technical Support specialists or email [email protected].
Authenticate and handle client credentials
All calls require the platform’s authentication credentials. Authentication credentials are sent using HTTP Basic Auth or OAuth 2.0 in the Tango portal:
- OAuth 2.0 client credentials: Allows you to establish a secure connection with API via an authorization token which uses your client ID and client secret.
- Basic client credentials: Allows you to authenticate your connection with the API using your platform name and API key.
The platform is responsible for managing access to its accounts, such as preventing ACC1 from placing an order using the ACC2 account. Requests from authenticated platforms against their accounts are implicitly trusted.
Note:Tango provides API keys and client credentials. See how to Manage Basic Auth API keys in Tango for API keys, and how to Manage OAuth client credentials in Tango.
Avoid browser-based API Calls
Tango doesn't allow web-based API calls. Attempts to do so will result in an authorization error (403.001) or Cross-Origin Resource Sharing (CORS) errors. CORS is a security feature that lets web pages request resources from a different domain. If you get CORS errors, you're trying to make POST calls from a browser, which Tango doesn't allow. For best practices, we highly recommend using non-browser tools for all API calls.
Protect platform keys
Never transmit your platform keys or client credentials via email or any other unsecured method. Design your system to allow for routine key changes. Change your keys immediately when employees who had access to the keys leave. If you suspect any suspicious activity on your platform, change your keys. We recommend rotating to new keys on a schedule. The OAuth tokens are generated from client credentials and expire in 24 hours (86400 seconds). Keys are managed through Tango portal. See how to get the client ID and secret from Tango . For more information on industry best practices in this area, see OWASP Top 10, #2
How often should you refresh your API keys?
The following recommendations are taken from ElevateAI as the general industry's suggestion:
- At least every six months – Rotating twice per year ensures keys don’t remain active for too long.
- With significant personnel/system changes – If developers, admins, or integrated systems that use the keys change, rotate the keys.
- After any known or potential compromises – If a key may have been exposed, generate a new one immediately.
- With extensive API changes – Big updates to API functionality may warrant issuing new keys.
The specific frequency will depend on your risk profile. More sensitive applications and data may warrant more frequent rotations, while less critical systems could go a year or longer between refresh cycles.
Cross-site scripting (XSS) and malicious behavior
Tango may reject requests based on content or behavior that could be exploitative. It includes requests containing insecure characters or requests that are not consistent with OWASP guidelines. See A03:2021 – Injection for reference.
Timeouts and Incremental Retry
Network unpredictability, infrastructure, and supplier factors are occasional network errors and must be planned for. We recommend holding the connection open for 15 seconds before terminating a call if there is no response.
We STRONGLY recommend that you use the idempotent "externalRefID" field to prevent accidental order duplication.
Additionally, best practice is to implement an exponential backoff or similar retry algorithm, in which the retry timeout increases after each unsuccessful attempt. Please ensure that all retry attempts hold the connections open for 15 seconds before terminating the call.
Recommended certificates
For Tango API, we recommend a Certificate Chain containing SSL/TLS and Certificate Authority (CA) for authentication:
SSL/TLS Certificate
Communication with the Tango API is handled via Transport Layer Security (TLS), a widely used protocol for secure message transmission over the Internet. As a Tango API client, make sure you have the Certificate Chain (an intermediate certificate) on your server. Not having the Certificate Chain prevents communication and exposes you to potential man-in-the-middle attacks. To accomplish this, we recommend adding the Certificate Authority (CA) to your system’s trusted list. If that’s not possible, you can include the certificate in your application. Major CAs deliver a bundled file containing the complete Certificate Chain, providing a single installation method for the certificate.
Certificate Authority (CA)
Tango uses Amazon Web Services (AWS) to create our SSL certificates. You can get AWS’s root and intermediate certificates from AWS Docs: Server Authentication Certs. If you choose to reference the Certificate Chain from your application’s code, the details on how to do this are highly specific to the library being used to make the connection, but here are a few examples to demonstrate the idea:
Example 1: SSL for Ruby language
https = Net::HTTP.new('integration-api.tangocard.com', 443)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
https.ca_file = File.join(File.dirname(__FILE__), "../ca_certs/AmazonRootCA1.pem")
https.request_get('/fake/example')Example 2: SSL for the PHP language
$curl = curl_init('https://integration-api.tangocard.com/fake/example');
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_CAINFO, __DIR__ . "../ca_certs/AmazonRootCA1.pem");
curl_exec($curl);Example 3: SSL for Python language
import requests
from requests.auth import HTTPBasicAuth
# SSL verify-peer is used by default.
requests.get('https://integration-api.tangocard.com/fake/example', auth=HTTPBasicAuth(username, password))Please note that in the Ruby and PHP examples, OpenSSL is being instructed to “VERIFY PEER”. This setting is essential because without it, you know your communication is encrypted, but don't know who you’re talking to.
Proxy and middleware system
Integrations that route requests to the Tango API through a proxy or middleware layer — such as Azure Integration Service (AIS), Azure API Management, MuleSoft, or any other API gateway — may receive a 403 Forbidden response even when the request is otherwise valid and properly authenticated.
The Tango API is served behind an AWS Application Load Balancer (ALB). The ALB enforces request validation rules that require the X-Forwarded-For (XFF) header to contain only IP addresses in the standard format defined by RFC 7239.
Many proxy and middleware systems — including certain configurations of Azure Integration Service, Azure API Management, and Salesforce outbound calls — automatically append an XFF header that includes both an IP address and a port number:
// Non-standard format (triggers 403)
X-Forwarded-For: 203.0.113.42:54321
When the ALB receives an XFF header value that does not conform to the IP-only format, it rejects the request at the infrastructure layer before it reaches the Tango application. This is why the response body is HTML rather than JSON, and why the server header identifies the load balancer (awselb/2.0) rather than the API service.
Important
This is not the same as the browser-based API call restriction documented in the Tango security guide. That restriction targets client-side JavaScript calls. This issue affects server-side middleware and proxy architectures.
How to Confirm This Is the Issue
Before applying the fix, verify that XFF header formatting is the cause:
- Capture the outgoing HTTP headers from your proxy or middleware layer.
- Look for an X-Forwarded-For header. If the value is in ip:port format, this article applies.
- To reproduce explicitly, send the same request with the XFF header manually set to an IP:port value. You should receive a 403. Then strip the port — you should receive a 200 OK.
Resolution
The fix is to ensure that the X-Forwarded-For header sent to Tango contains only a well-formed IP address, with no port suffix. The method for doing this depends on your middleware platform.
Azure Integration Service / Azure API Management Add an outbound policy to explicitly override the XFF header before forwarding the request to Tango. Set it to your static outbound public IP address:
<set-header name="X-Forwarded-For" exists-action="override">
<value>{{YOUR_OUTBOUND_PUBLIC_IP}}</value>
</set-header>
Other Proxy / Middleware Platforms The approach is the same regardless of platform: intercept the outbound request and rewrite or remove the XFF header before it reaches Tango. Common approaches include:
- MuleSoft: Use a Remove Request Header or Set Variable component to strip/rewrite XFF before the HTTP Request component.
- AWS API Gateway: Use a Lambda authorizer or an integration request mapping template to remove the port from the forwarded IP address.
- Nginx / reverse proxy: Use proxy_set_header X-Forwarded-For $remote_addr; to pass only the IP.
If This Does Not Resolve the Issue
If you have confirmed the XFF header is in the correct format, and you are still receiving a 403 Forbidden, consider the following alternative causes:
- Expired or invalid access token. Tango OAuth tokens are valid for 24 hours. Ensure your integration refreshes the token before expiry and that the Bearer token in the Authorization header is current.
- Browser-based API call detected. Tango blocks calls originating from a browser context (e.g., client-side JavaScript fetch). All Tango API calls must be made from a server-side or backend process. See the Tango Security Guide for details.
- Incorrect API endpoint. Ensure you are calling the correct environment (sandbox vs. production). Sandbox: integration-api.tangocard.com. Production: api.tangocard.com.
Updated 17 days ago
