Skip to main content

Authentication

NotaryCam API uses JWT (JSON Web Token) authentication. Exchange your API credentials for a token, then include it in all subsequent requests.

Quick Overview

Step 1: Obtain a Token

Endpoint

POST /api/v4/authorize/

Request

const axios = require('axios');

async function authenticate() {
const response = await axios.post(
'{BASE_URL}/api/v4/authorize/',
{
partnerId: 'your-partner-id',
apiKey: 'your-api-key',
apiSecret: 'your-api-secret'
},
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
);

return response.data.token;
}

// Usage
const token = await authenticate();
console.log('Token:', token);

Response

{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXJ0bmVySWQiOiJ5b3VyLXBhcnRuZXItaWQiLCJpYXQiOjE3MDk1NjgwMDAsImV4cCI6MTcwOTY1NDQwMH0.abc123def456"
}

Step 2: Use the Token

Include the token in the Authorization header for all API requests:

Authorization: Bearer {your-token}

Example API Request

const axios = require('axios');

async function getTransaction(transactionId, token) {
const response = await axios.get(
`{BASE_URL}/api/v4/transactions/${transactionId}`,
{
headers: {
'Authorization': `Bearer ${token}`
}
}
);

return response.data;
}

// Usage
const transaction = await getTransaction('transaction-id-123', token);

Token Expiration

Expiration Time

  • Lifetime: 24 hours from issuance
  • Check expiration: Decode the JWT to see exp claim

Handling Expiration

Implement token refresh logic:

class NotaryCamAPI {
constructor(baseUrl, credentials) {
this.baseUrl = baseUrl;
this.credentials = credentials;
this.token = null;
this.tokenExpiry = null;
}

async ensureAuthenticated() {
const now = Date.now();

// Refresh token if expired or not set
if (!this.token || !this.tokenExpiry || now >= this.tokenExpiry) {
await this.authenticate();
}
}

async authenticate() {
const response = await axios.post(
`${this.baseUrl}/api/v4/authorize/`,
this.credentials,
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
);

this.token = response.data.token;

// Set expiry to 23 hours from now (1 hour buffer)
this.tokenExpiry = Date.now() + (23 * 60 * 60 * 1000);
}

async makeRequest(method, endpoint, data = null) {
await this.ensureAuthenticated();

return axios({
method,
url: `${this.baseUrl}${endpoint}`,
data,
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
}
});
}
}

// Usage
const api = new NotaryCamAPI('{BASE_URL}', {
partnerId: process.env.NOTARYCAM_PARTNER_ID,
apiKey: process.env.NOTARYCAM_API_KEY,
apiSecret: process.env.NOTARYCAM_API_SECRET
});

// Automatically handles token refresh
const transaction = await api.makeRequest('GET', '/api/v4/transactions/123');

Security Best Practices

1. Protect Your Credentials

Never Expose Credentials

Never commit API credentials to version control or expose them in client-side code.

** Good Practices:**

// Use environment variables
const credentials = {
partnerId: process.env.NOTARYCAM_PARTNER_ID,
apiKey: process.env.NOTARYCAM_API_KEY,
apiSecret: process.env.NOTARYCAM_API_SECRET
};

// Use a secrets manager
const credentials = await secretsManager.getCredentials('notarycam');

** Bad Practices:**

// Don't hardcode credentials
const credentials = {
partnerId: 'partner-abc123', // Never do this!
apiKey: 'key-xyz789',
apiSecret: 'secret-def456'
};

// Don't commit .env files
// Add .env to .gitignore

2. Secure Token Storage

Store tokens securely:

  • Server-side: Memory or encrypted cache
  • Never in: Cookies, localStorage, or client-side code
  • HTTPS only: Always use HTTPS for API calls

3. Rotate Credentials Regularly

  • Rotate API keys periodically
  • Update credentials if compromised
  • Use separate credentials for different environments

4. Monitor API Usage

  • Log authentication attempts
  • Monitor for unusual API activity
  • Set up alerts for failed authentication

Error Handling

Common Authentication Errors

Error CodeMeaningSolution
400Bad RequestCheck request format and required fields
401UnauthorizedVerify credentials are correct
403ForbiddenCheck API access permissions
429Too Many RequestsImplement rate limiting and backoff

Handling Authentication Errors

async function authenticateWithRetry(maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await axios.post(
'{BASE_URL}/api/v4/authorize/',
{
partnerId: process.env.NOTARYCAM_PARTNER_ID,
apiKey: process.env.NOTARYCAM_API_KEY,
apiSecret: process.env.NOTARYCAM_API_SECRET
},
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
);

return response.data.token;

} catch (error) {
if (error.response?.status === 401) {
throw new Error('Invalid credentials - check your API keys');
}

if (error.response?.status === 429) {
const delay = Math.pow(2, i) * 1000; // Exponential backoff
console.log(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}

if (i === maxRetries - 1) throw error;
}
}
}

Testing Authentication

Test Authentication

Always test authentication before going to production:

const api = new NotaryCamAPI('{BASE_URL}', {
partnerId: process.env.NOTARYCAM_PARTNER_ID,
apiKey: process.env.NOTARYCAM_API_KEY,
apiSecret: process.env.NOTARYCAM_API_SECRET
});

Verify Token

Decode the JWT to verify contents (for debugging):

// Decode JWT (base64)
function decodeJWT(token) {
const parts = token.split('.');
const payload = Buffer.from(parts[1], 'base64').toString();
return JSON.parse(payload);
}

const decoded = decodeJWT(token);
console.log('Token expires:', new Date(decoded.exp * 1000));

Next Steps

Now that you understand authentication:

  1. Test it → Try authenticating in sandbox
  2. Build wrapper → Create an API client class
  3. ContinueQuick Start Guide
  4. Learn moreSecurity Best Practices

Troubleshooting

"Invalid credentials" error?

  • Double-check Partner ID, API Key, and API Secret
  • Ensure using correct environment and base URL
  • Verify credentials haven't expired

Token expires too quickly?

  • Implement automatic token refresh
  • Check system clock is synchronized
  • Consider token caching strategy

Need help?