Skip to content

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 Bearer followed by a space, then clientID:apiKey separated 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:

Authorization: Bearer NC12345:sk_live_abc123xyz789
Content-Type: application/json

Body:

{
  "accountId": "A12345",
  "amount": 1000
}

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:

  1. Authorization Header (Recommended, REQUIRED for GET endpoints)
  2. 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:

{
  "statusCode": 103,
  "statusDesc": "Invalid developer API Key"
}

Invalid Credentials

If the provided credentials (header or body) are invalid:

{
  "statusCode": 103,
  "statusDesc": "Invalid developer API Key"
}

Unauthorized Access

If credentials are valid but lack permission for the requested operation:

{
  "statusCode": 110,
  "statusDesc": "You do not have the required permissions"
}

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

  1. Update one endpoint to use headers
  2. Test thoroughly
  3. Update remaining endpoints
  4. 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]