Authorization headers¶
Benefits of Authorization Header¶
- Improved Security: Credentials are separated from business data, reducing accidental exposure when sharing request examples
- Cleaner Request Bodies: Keep your request payloads focused on business logic only
- Industry Standard: Aligns with REST API best practices
- Debugging Safety: Share request bodies with team members without worrying about credential exposure
Authorization Header¶
Required Header Format¶
TAPI uses the standard Authorization header with a Bearer token format:
| Header | Format | Example |
|---|---|---|
Authorization | Bearer {clientID}:{apiKey} | Authorization: Bearer NC12345:sk_live_abc123xyz789 |
Important Notes¶
- The format is
Bearerfollowed by a space, thenclientID:apiKeyseparated by a colon - Header names are case-insensitive (per HTTP specification)
- The Authorization header takes precedence over body parameters if both are provided
- The Bearer token must contain both clientID and apiKey separated by a colon (:)
- GET endpoints REQUIRE the Authorization header - credentials cannot be passed in URL parameters
Migration Guide¶
Before (Body Authentication)¶
{
"developerAPIKey": "sk_live_abc123xyz789",
"clientID": "NC12345",
"accountId": "A12345",
"amount": 1000
}
After (Authorization Header)¶
Headers:
Body:
GET Endpoints (Authorization Header Required)¶
For GET endpoints, authentication MUST be provided via the Authorization header since there's no request body:
# GET endpoints require Authorization header
curl -X GET https://api-sandboxdash.norcapsecurities.com/tapiv3/parties \
-H "Authorization: Bearer NC12345:sk_live_abc123xyz789"
# These endpoints include: parties, entities, trades, offerings, issuers, links, exports, jobs, permissions
Implementation Examples¶
cURL¶
curl -X POST https://api-sandboxdash.norcapsecurities.com/tapiv3/createTrade \
-H "Content-Type: application/json" \
-H "Authorization: Bearer NC12345:sk_live_abc123xyz789" \
-d '{
"accountId": "A12345",
"offeringId": "O54321",
"units": 100
}'
JavaScript (Fetch API)¶
const response = await fetch('https://api-sandboxdash.norcapsecurities.com/tapiv3/createTrade', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer NC12345:sk_live_abc123xyz789'
},
body: JSON.stringify({
accountId: 'A12345',
offeringId: 'O54321',
units: 100
})
});
JavaScript (Axios)¶
const axios = require('axios');
const response = await axios.post(
'https://api-sandboxdash.norcapsecurities.com/tapiv3/createTrade',
{
accountId: 'A12345',
offeringId: 'O54321',
units: 100
},
{
headers: {
'Authorization': 'Bearer NC12345:sk_live_abc123xyz789'
}
}
);
Python (Requests)¶
import requests
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer NC12345:sk_live_abc123xyz789'
}
data = {
'accountId': 'A12345',
'offeringId': 'O54321',
'units': 100
}
response = requests.post(
'https://api-sandboxdash.norcapsecurities.com/tapiv3/createTrade',
headers=headers,
json=data
)
PHP (cURL)¶
$ch = curl_init('https://api-sandboxdash.norcapsecurities.com/tapiv3/createTrade');
$headers = [
'Content-Type: application/json',
'Authorization: Bearer NC12345:sk_live_abc123xyz789'
];
$data = [
'accountId' => 'A12345',
'offeringId' => 'O54321',
'units' => 100
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
C# (.NET HttpClient)¶
using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer NC12345:sk_live_abc123xyz789");
var data = new
{
accountId = "A12345",
offeringId = "O54321",
units = 100
};
var json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://api-sandboxdash.norcapsecurities.com/tapiv3/createTrade",
content
);
Java (OkHttp)¶
import okhttp3.*;
OkHttpClient client = new OkHttpClient();
String json = "{\"accountId\":\"A12345\",\"offeringId\":\"O54321\",\"units\":100}";
RequestBody body = RequestBody.create(
json,
MediaType.parse("application/json")
);
Request request = new Request.Builder()
.url("https://api-sandboxdash.norcapsecurities.com/tapiv3/createTrade")
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer NC12345:sk_live_abc123xyz789")
.post(body)
.build();
Response response = client.newCall(request).execute();
Ruby (Net::HTTP)¶
require 'net/http'
require 'json'
uri = URI('https://api-sandboxdash.norcapsecurities.com/tapiv3/createTrade')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer NC12345:sk_live_abc123xyz789'
request.body = {
accountId: 'A12345',
offeringId: 'O54321',
units: 100
}.to_json
response = http.request(request)
Backwards Compatibility¶
Both Methods Supported¶
Both authentication methods are supported:
- Authorization Header (Recommended, REQUIRED for GET endpoints)
- Body Parameters (POST/PUT only, not available for GET)
Method Availability by HTTP Verb¶
| HTTP Method | Header Auth | Body Auth | Notes |
|---|---|---|---|
| GET | ✅ Required | ❌ N/A | No request body in GET requests |
| POST | ✅ Supported | ✅ Supported | Header auth recommended |
| PUT | ✅ Supported | ✅ Supported | Header auth recommended |
| DELETE | ✅ Supported | ✅ Supported | Header auth recommended |
Priority Order¶
If credentials are provided in both headers and body (POST/PUT only):
- Headers take precedence
- Body credentials are ignored
Example with Both¶
# Authorization header will be used, body credentials ignored
curl -X POST https://api-sandboxdash.norcapsecurities.com/tapiv3/getAccount \
-H "Authorization: Bearer NC12345:sk_live_abc123xyz789" \
-d '{
"developerAPIKey": "old_key_ignored",
"clientID": "old_id_ignored",
"accountId": "A12345"
}'
Error Handling¶
Missing Headers¶
If authentication headers are missing and no body credentials are provided:
Invalid Credentials¶
If the provided credentials (header or body) are invalid:
Unauthorized Access¶
If credentials are valid but lack permission for the requested operation:
Best Practices¶
1. Environment Variables¶
Store credentials in environment variables, not in code:
// Good
const apiKey = process.env.TAPI_API_KEY;
const clientId = process.env.TAPI_CLIENT_ID;
// Bad
const apiKey = 'sk_live_abc123xyz789'; // Never hardcode!
2. Configuration Management¶
Create a centralized configuration for API calls:
// config.js
module.exports = {
baseURL: 'https://api-sandboxdash.norcapsecurities.com/tapiv3',
headers: {
'Authorization': `Bearer ${process.env.TAPI_CLIENT_ID}:${process.env.TAPI_API_KEY}`
}
};
// usage.js
const config = require('./config');
const axios = require('axios');
const client = axios.create({
baseURL: config.baseURL,
headers: config.headers
});
// Now all requests automatically include auth headers
const response = await client.post('/createTrade', {
accountId: 'A12345',
offeringId: 'O54321',
units: 100
});
3. Error Handling¶
Always handle authentication errors gracefully:
try {
const response = await makeApiCall();
// Process successful response
} catch (error) {
if (error.response?.status === 401) {
console.error('Authentication failed. Check your API credentials.');
} else if (error.response?.status === 403) {
console.error('Permission denied. Your API key may lack required scopes.');
} else {
console.error('API call failed:', error.message);
}
}
4. Logging and Debugging¶
When logging requests, exclude sensitive headers:
// Create a sanitized request log
function logRequest(config) {
const sanitized = {
...config,
headers: {
...config.headers,
'Authorization': 'Bearer ***REDACTED***'
}
};
console.log('API Request:', sanitized);
}
Testing Your Implementation¶
1. Test Environment¶
Start with the sandbox environment:
- Sandbox URL:
https://api-sandboxdash.norcapsecurities.com/tapiv3 - Use your sandbox credentials
2. Verify Headers Are Sent¶
Use a tool like curl with -v flag to see headers:
curl -v -X POST https://api-sandboxdash.norcapsecurities.com/tapiv3/ping \
-H "Authorization: Bearer your_sandbox_id:your_sandbox_key"
3. Gradual Migration¶
- Update one endpoint to use headers
- Test thoroughly
- Update remaining endpoints
- Remove body credentials once all endpoints are updated
Frequently Asked Questions¶
Q: Is Authorization header authentication available in all environments?¶
A: Authorization header support varies by environment. Check with your account manager or test in your sandbox environment to confirm availability.
Q: Will my existing integrations break?¶
A: No. Body-based authentication will continue to work for POST/PUT/DELETE requests. However, GET endpoints require header authentication since they don't have request bodies.
Q: Do I need to update my GET endpoint calls?¶
A: Yes. All GET endpoints require the Authorization header. You cannot pass credentials as URL parameters for security reasons.
Q: Can I use different authentication methods for different endpoints?¶
A: Yes. You can use headers for some calls and body parameters for others. Each request is authenticated independently.
Q: Is the header name case-sensitive?¶
A: No. HTTP headers are case-insensitive. Authorization, authorization, and AUTHORIZATION all work.
Q: What if I accidentally send credentials in both headers and body?¶
A: Headers take precedence. Body credentials will be ignored if headers are present.
Q: Do webhook endpoints require these headers?¶
A: No. Webhook endpoints (callbacks from external services like DocuSign) have their own authentication mechanisms.
Support¶
For questions or issues with header authentication:
- Technical Support: support@northcapital.com
- API Documentation: [https\://api-sandboxdash.norcapsecurities.com/documentation]
- Status Page: [https\://status.northcapital.com]