Your First Transaction
This tutorial walks you through creating a complete notarization transaction from start to finish. By the end, you'll have created users, uploaded documents, and activated a transaction ready for notarization.
What You'll Build
Authenticate with the API
Create user accounts for participants
Create a transaction
Upload documents
Set transaction metadata (optional)
Activate the transaction
Time to complete: ~30 minutes
Prerequisites
Before starting, ensure you have:
- API credentials (Partner ID, API Key, API Secret)
- Department ID
- Workflow ID
- At least one PDF document to test with
Complete Workflow
Step-by-Step Implementation
Step 1: Authenticate
First, exchange your credentials for a JWT token.
- JavaScript/Node.js
- Python
- C#/.NET
const axios = require('axios');
const BASE_URL = '{BASE_URL}';
// Step 1: Authenticate
async function authenticate() {
console.log('Step 1: Authenticating...');
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'
}
}
);
console.log(' Authenticated successfully');
return response.data.token;
}
const token = await authenticate();
import requests
import os
BASE_URL = '{BASE_URL}'
# Step 1: Authenticate
def authenticate():
print('Step 1: Authenticating...')
response = requests.post(
f'{BASE_URL}/api/v4/authorize/',
data={
'partnerId': os.environ['NOTARYCAM_PARTNER_ID'],
'apiKey': os.environ['NOTARYCAM_API_KEY'],
'apiSecret': os.environ['NOTARYCAM_API_SECRET']
},
headers={'Content-Type': 'application/x-www-form-urlencoded'}
)
print(' Authenticated successfully')
return response.json()['token']
token = authenticate()
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
const string BASE_URL = "{BASE_URL}";
// Step 1: Authenticate
public async Task<string> Authenticate()
{
Console.WriteLine("Step 1: Authenticating...");
using var client = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("partnerId", Environment.GetEnvironmentVariable("NOTARYCAM_PARTNER_ID")),
new KeyValuePair<string, string>("apiKey", Environment.GetEnvironmentVariable("NOTARYCAM_API_KEY")),
new KeyValuePair<string, string>("apiSecret", Environment.GetEnvironmentVariable("NOTARYCAM_API_SECRET"))
});
var response = await client.PostAsync($"{BASE_URL}/api/v4/authorize/", content);
var json = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<AuthResponse>(json);
Console.WriteLine(" Authenticated successfully");
return result.Token;
}
string token = await Authenticate();
Store the token for use in all subsequent requests. It's valid for 24 hours.
Step 2: Create Users
Create user accounts for all participants in your transaction. In this example, we'll create two signers.
- JavaScript/Node.js
- Python
- C#/.NET
// Step 2: Create Users
async function createParticipants(token) {
console.log('Step 2: Creating users...');
// Create first signer
const user1Response = await axios.post(
`${BASE_URL}/api/v4/users`,
{
departments: [process.env.NOTARYCAM_DEPARTMENT_ID],
email: 'john.doe@example.com',
firstName: 'John',
lastName: 'Doe',
phone: '+15551234567',
dateOfBirth: '1985-06-15T00:00:00.000Z',
address: {
country: 'US',
street: '123 Main Street',
city: 'San Francisco',
state: 'CA',
postalCode: '94102'
}
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
const user1Id = user1Response.data.user._id;
console.log(` Created user 1: ${user1Id}`);
// Create second signer
const user2Response = await axios.post(
`${BASE_URL}/api/v4/users`,
{
departments: [process.env.NOTARYCAM_DEPARTMENT_ID],
email: 'jane.smith@example.com',
firstName: 'Jane',
lastName: 'Smith',
phone: '+15559876543',
dateOfBirth: '1990-03-22T00:00:00.000Z',
address: {
country: 'US',
street: '456 Oak Avenue',
city: 'Austin',
state: 'TX',
postalCode: '78701'
}
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
const user2Id = user2Response.data.user._id;
console.log(` Created user 2: ${user2Id}`);
return [user1Id, user2Id];
}
const [user1Id, user2Id] = await createParticipants(token);
# Step 2: Create Users
def create_participants(token):
print('Step 2: Creating users...')
headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
# Create first signer
user1_response = requests.post(
f'{BASE_URL}/api/v4/users',
json={
'departments': [os.environ['NOTARYCAM_DEPARTMENT_ID']],
'email': 'john.doe@example.com',
'firstName': 'John',
'lastName': 'Doe',
'phone': '+15551234567',
'dateOfBirth': '1985-06-15T00:00:00.000Z',
'address': {
'country': 'US',
'street': '123 Main Street',
'city': 'San Francisco',
'state': 'CA',
'postalCode': '94102'
}
},
headers=headers
)
user1_id = user1_response.json()['user']['_id']
print(f' Created user 1: {user1_id}')
# Create second signer
user2_response = requests.post(
f'{BASE_URL}/api/v4/users',
json={
'departments': [os.environ['NOTARYCAM_DEPARTMENT_ID']],
'email': 'jane.smith@example.com',
'firstName': 'Jane',
'lastName': 'Smith',
'phone': '+15559876543',
'dateOfBirth': '1990-03-22T00:00:00.000Z',
'address': {
'country': 'US',
'street': '456 Oak Avenue',
'city': 'Austin',
'state': 'TX',
'postalCode': '78701'
}
},
headers=headers
)
user2_id = user2_response.json()['user']['_id']
print(f' Created user 2: {user2_id}')
return [user1_id, user2_id]
user1_id, user2_id = create_participants(token)
// Step 2: Create Users
public async Task<List<string>> CreateParticipants(string token)
{
Console.WriteLine("Step 2: Creating users...");
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
// Create first signer
var user1Data = new
{
departments = new[] { Environment.GetEnvironmentVariable("NOTARYCAM_DEPARTMENT_ID") },
email = "john.doe@example.com",
firstName = "John",
lastName = "Doe",
phone = "+15551234567",
dateOfBirth = "1985-06-15T00:00:00.000Z",
address = new
{
country = "US",
street = "123 Main Street",
city = "San Francisco",
state = "CA",
postalCode = "94102"
}
};
var user1Json = JsonConvert.SerializeObject(user1Data);
var user1Content = new StringContent(user1Json, Encoding.UTF8, "application/json");
var user1Response = await client.PostAsync($"{BASE_URL}/api/v4/users", user1Content);
var user1Result = JsonConvert.DeserializeObject<UserResponse>(await user1Response.Content.ReadAsStringAsync());
string user1Id = user1Result.User.Id;
Console.WriteLine($" Created user 1: {user1Id}");
// Create second signer
var user2Data = new
{
departments = new[] { Environment.GetEnvironmentVariable("NOTARYCAM_DEPARTMENT_ID") },
email = "jane.smith@example.com",
firstName = "Jane",
lastName = "Smith",
phone = "+15559876543",
dateOfBirth = "1990-03-22T00:00:00.000Z",
address = new
{
country = "US",
street = "456 Oak Avenue",
city = "Austin",
state = "TX",
postalCode = "78701"
}
};
var user2Json = JsonConvert.SerializeObject(user2Data);
var user2Content = new StringContent(user2Json, Encoding.UTF8, "application/json");
var user2Response = await client.PostAsync($"{BASE_URL}/api/v4/users", user2Content);
var user2Result = JsonConvert.DeserializeObject<UserResponse>(await user2Response.Content.ReadAsStringAsync());
string user2Id = user2Result.User.Id;
Console.WriteLine($" Created user 2: {user2Id}");
return new List<string> { user1Id, user2Id };
}
var userId = await CreateParticipants(token);
Common roles include: signer, notary, witness, observer, preparer, submitter, credible-witness. See User Roles for details.
Step 3: Create Transaction
Now create the transaction and assign participants with their roles.
- JavaScript/Node.js
- Python
- C#/.NET
// Step 3: Create Transaction
async function createTransaction(token, user1Id, user2Id) {
console.log('Step 3: Creating transaction...');
const response = await axios.post(
`${BASE_URL}/api/v4/transactions/`,
{
department: process.env.NOTARYCAM_DEPARTMENT_ID, // Required
participants: [
{ user: user1Id, role: 'signer' },
{ user: user2Id, role: 'signer' }
],
workflow: process.env.NOTARYCAM_WORKFLOW_ID // Optional - auto-assigned if not provided
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
const transactionId = response.data.transaction._id;
console.log(` Transaction created: ${transactionId}`);
// Save participant room URLs
response.data.transaction.participants.forEach((p, i) => {
console.log(` Participant ${i + 1} room: ${p.roomURL}`);
});
return transactionId;
}
const transactionId = await createTransaction(token, user1Id, user2Id);
# Step 3: Create Transaction
def create_transaction(token, user1_id, user2_id):
print('Step 3: Creating transaction...')
response = requests.post(
f'{BASE_URL}/api/v4/transactions/',
json={
'department': os.environ['NOTARYCAM_DEPARTMENT_ID'], # Required
'participants': [
{'user': user1_id, 'role': 'signer'},
{'user': user2_id, 'role': 'signer'}
],
'workflow': os.environ['NOTARYCAM_WORKFLOW_ID'] # Optional - auto-assigned if not provided
},
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)
transaction_id = response.json()['transaction']['_id']
print(f' Transaction created: {transaction_id}')
# Save participant room URLs
for i, p in enumerate(response.json()['transaction']['participants']):
print(f' Participant {i + 1} room: {p["roomURL"]}')
return transaction_id
transaction_id = create_transaction(token, user1_id, user2_id)
// Step 3: Create Transaction
public async Task<string> CreateTransaction(string token, string user1Id, string user2Id)
{
Console.WriteLine("Step 3: Creating transaction...");
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var transactionData = new
{
department = Environment.GetEnvironmentVariable("NOTARYCAM_DEPARTMENT_ID"), // Required
participants = new[]
{
new { user = user1Id, role = "signer" },
new { user = user2Id, role = "signer" }
},
workflow = Environment.GetEnvironmentVariable("NOTARYCAM_WORKFLOW_ID") // Optional - auto-assigned if not provided
};
var json = JsonConvert.SerializeObject(transactionData);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync($"{BASE_URL}/api/v4/transactions/", content);
var result = JsonConvert.DeserializeObject<TransactionResponse>(await response.Content.ReadAsStringAsync());
string transactionId = result.Transaction.Id;
Console.WriteLine($" Transaction created: {transactionId}");
// Save participant room URLs
for (int i = 0; i < result.Transaction.Participants.Length; i++)
{
Console.WriteLine($" Participant {i + 1} room: {result.Transaction.Participants[i].RoomURL}");
}
return transactionId;
}
string transactionId = await CreateTransaction(token, userIds[0], userIds[1]);
Important: Save the participant roomURL values - participants will use these to join the notarization session.
Step 4: Upload Documents
Upload documents using multipart form data. The request requires two form fields: the file(s) and a documentData JSON field that maps each file to its document type.
- JavaScript/Node.js
- Python
- C#/.NET
const FormData = require('form-data');
const fs = require('fs');
// Step 4: Upload Documents
async function uploadDocuments(token, transactionId) {
console.log('Step 4: Uploading documents...');
const form = new FormData();
// Attach the file
form.append('documents', fs.createReadStream('./sample-document.pdf'));
// Attach document metadata (must match filenames)
form.append('documentData', JSON.stringify([
{ fileName: 'sample-document.pdf', type: 'notarize' }
]));
const response = await axios.post(
`${BASE_URL}/api/v4/transactions/${transactionId}/documents`,
form,
{
headers: {
'Authorization': `Bearer ${token}`,
...form.getHeaders()
}
}
);
console.log(` Uploaded ${response.data.documentsReceived} document(s)`);
}
await uploadDocuments(token, transactionId);
# Step 4: Upload Documents
def upload_documents(token, transaction_id):
print('Step 4: Uploading documents...')
files = {
'documents': ('sample-document.pdf', open('./sample-document.pdf', 'rb'), 'application/pdf')
}
data = {
'documentData': json.dumps([
{'fileName': 'sample-document.pdf', 'type': 'notarize'}
])
}
response = requests.post(
f'{BASE_URL}/api/v4/transactions/{transaction_id}/documents',
files=files,
data=data,
headers={
'Authorization': f'Bearer {token}'
}
)
print(f' Uploaded {response.json()["documentsReceived"]} document(s)')
upload_documents(token, transaction_id)
// Step 4: Upload Documents
public async Task UploadDocuments(string token, string transactionId)
{
Console.WriteLine("Step 4: Uploading documents...");
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
using var form = new MultipartFormDataContent();
// Attach the file
var fileContent = new ByteArrayContent(File.ReadAllBytes("./sample-document.pdf"));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
form.Add(fileContent, "documents", "sample-document.pdf");
// Attach document metadata
var documentData = JsonConvert.SerializeObject(new[]
{
new { fileName = "sample-document.pdf", type = "notarize" }
});
form.Add(new StringContent(documentData), "documentData");
var response = await client.PostAsync(
$"{BASE_URL}/api/v4/transactions/{transactionId}/documents",
form
);
var result = JsonConvert.DeserializeObject<dynamic>(await response.Content.ReadAsStringAsync());
Console.WriteLine($" Uploaded {result.documentsReceived} document(s)");
}
await UploadDocuments(token, transactionId);
Document Types:
notarize- Requires notarizationsign- Signature onlysupport- Supporting document (no signature)other- Other document type
Step 5: Set Metadata (Optional)
Add custom metadata for tracking and reporting. This step is optional but recommended.
- JavaScript/Node.js
- Python
- C#/.NET
// Step 5: Set Metadata (Optional)
async function setMetadata(token, transactionId) {
console.log('Step 5: Setting metadata...');
const response = await axios.put(
`${BASE_URL}/api/v4/transactions/${transactionId}/metadata`,
{
notes: ['First API transaction', 'Test integration'],
customFields: [
{ name: 'Project', value: 'API Integration' },
{ name: 'Environment', value: 'Development' }
],
realEstate: {
loanNumber: 'TEST-123456',
transactionType: 'refinance',
propertyAddress: {
street: '789 Property Lane',
city: 'Seattle',
state: 'WA',
postalCode: '98101',
country: 'US'
}
}
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
console.log(' Metadata set successfully');
}
await setMetadata(token, transactionId);
# Step 5: Set Metadata (Optional)
def set_metadata(token, transaction_id):
print('Step 5: Setting metadata...')
response = requests.put(
f'{BASE_URL}/api/v4/transactions/{transaction_id}/metadata',
json={
'notes': ['First API transaction', 'Test integration'],
'customFields': [
{'name': 'Project', 'value': 'API Integration'},
{'name': 'Environment', 'value': 'Development'}
],
'realEstate': {
'loanNumber': 'TEST-123456',
'transactionType': 'refinance',
'propertyAddress': {
'street': '789 Property Lane',
'city': 'Seattle',
'state': 'WA',
'postalCode': '98101',
'country': 'US'
}
}
},
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)
print(' Metadata set successfully')
set_metadata(token, transaction_id)
// Step 5: Set Metadata (Optional)
public async Task SetMetadata(string token, string transactionId)
{
Console.WriteLine("Step 5: Setting metadata...");
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var metadata = new
{
notes = new[] { "First API transaction", "Test integration" },
customFields = new[]
{
new { name = "Project", value = "API Integration" },
new { name = "Environment", value = "Development" }
},
realEstate = new
{
loanNumber = "TEST-123456",
transactionType = "refinance",
propertyAddress = new
{
street = "789 Property Lane",
city = "Seattle",
state = "WA",
postalCode = "98101",
country = "US"
}
}
};
var json = JsonConvert.SerializeObject(metadata);
var content = new StringContent(json, Encoding.UTF8, "application/json");
await client.PutAsync($"{BASE_URL}/api/v4/transactions/{transactionId}/metadata", content);
Console.WriteLine(" Metadata set successfully");
}
await SetMetadata(token, transactionId);
Step 6: Activate Transaction
The final step! This triggers notifications and makes the transaction available to participants.
- JavaScript/Node.js
- Python
- C#/.NET
// Step 6: Activate Transaction
async function activateTransaction(token, transactionId) {
console.log('Step 6: Activating transaction...');
const response = await axios.put(
`${BASE_URL}/api/v4/transactions/${transactionId}/activate`,
{},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
console.log(' Transaction activated!');
console.log('\n Success! Your transaction is now active.');
}
await activateTransaction(token, transactionId);
# Step 6: Activate Transaction
def activate_transaction(token, transaction_id):
print('Step 6: Activating transaction...')
response = requests.put(
f'{BASE_URL}/api/v4/transactions/{transaction_id}/activate',
json={},
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)
print(' Transaction activated!')
print('\n Success! Your transaction is now active.')
activate_transaction(token, transaction_id)
// Step 6: Activate Transaction
public async Task ActivateTransaction(string token, string transactionId)
{
Console.WriteLine("Step 6: Activating transaction...");
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var content = new StringContent("{}", Encoding.UTF8, "application/json");
await client.PutAsync($"{BASE_URL}/api/v4/transactions/{transactionId}/activate", content);
Console.WriteLine(" Transaction activated!");
Console.WriteLine("\n Success! Your transaction is now active.");
}
await ActivateTransaction(token, transactionId);
What Happens Next?
After activation:
- ** Notifications Sent** - Participants receive emails with their room URLs
- ** Session Scheduled** - Transaction becomes available for the notarization session
- ** Webhooks Triggered** - You receive webhook events for status changes
- ** Participants Join** - Users can access their room URLs to join the session
Complete Example
Here's the entire workflow in one script:
- JavaScript/Node.js
- Python
const axios = require('axios');
require('dotenv').config();
const BASE_URL = '{BASE_URL}';
async function createFirstTransaction() {
try {
// Step 1: Authenticate
console.log('Step 1: Authenticating...');
const authResponse = 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' } }
);
const token = authResponse.data.token;
console.log(' Authenticated\n');
// Step 2: Create Users
console.log('Step 2: Creating users...');
const headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
const user1 = await axios.post(`${BASE_URL}/api/v4/users`, {
departments: [process.env.NOTARYCAM_DEPARTMENT_ID],
email: 'john.doe@example.com',
firstName: 'John',
lastName: 'Doe',
phone: '+15551234567',
dateOfBirth: '1985-06-15T00:00:00.000Z',
address: {
country: 'US',
street: '123 Main St',
city: 'San Francisco',
state: 'CA',
postalCode: '94102'
}
}, { headers });
const user2 = await axios.post(`${BASE_URL}/api/v4/users`, {
departments: [process.env.NOTARYCAM_DEPARTMENT_ID],
email: 'jane.smith@example.com',
firstName: 'Jane',
lastName: 'Smith',
phone: '+15559876543',
dateOfBirth: '1990-03-22T00:00:00.000Z',
address: {
country: 'US',
street: '456 Oak Ave',
city: 'Austin',
state: 'TX',
postalCode: '78701'
}
}, { headers });
console.log(` Created users\n`);
// Step 3: Create Transaction
console.log('Step 3: Creating transaction...');
const transaction = await axios.post(`${BASE_URL}/api/v4/transactions/`, {
department: process.env.NOTARYCAM_DEPARTMENT_ID, // Required
participants: [
{ user: user1.data.user._id, role: 'signer' },
{ user: user2.data.user._id, role: 'signer' }
],
workflow: process.env.NOTARYCAM_WORKFLOW_ID
}, { headers });
const transactionId = transaction.data.transaction._id;
console.log(` Transaction created: ${transactionId}\n`);
// Step 4: Upload Documents
console.log('Step 4: Uploading documents...');
const FormData = require('form-data');
const fs = require('fs');
const form = new FormData();
form.append('documents', fs.createReadStream('./sample.pdf'));
form.append('documentData', JSON.stringify([
{ fileName: 'sample.pdf', type: 'notarize' }
]));
await axios.post(
`${BASE_URL}/api/v4/transactions/${transactionId}/documents`,
form,
{ headers: { ...headers, ...form.getHeaders() } }
);
console.log(' Documents uploaded\n');
// Step 5: Set Metadata (Optional)
console.log('Step 5: Setting metadata...');
await axios.put(
`${BASE_URL}/api/v4/transactions/${transactionId}/metadata`,
{
notes: ['First API transaction'],
customFields: [{ name: 'Source', value: 'API Tutorial' }]
},
{ headers }
);
console.log(' Metadata set\n');
// Step 6: Activate
console.log('Step 6: Activating transaction...');
await axios.put(
`${BASE_URL}/api/v4/transactions/${transactionId}/activate`,
{},
{ headers }
);
console.log(' Transaction activated\n');
console.log(' Complete! Transaction ID:', transactionId);
console.log('\nParticipant Room URLs:');
transaction.data.transaction.participants.forEach((p, i) => {
console.log(` ${i + 1}. ${p.user.email}: ${p.roomURL}`);
});
} catch (error) {
console.error(' Error:', error.response?.data || error.message);
process.exit(1);
}
}
// Run it
createFirstTransaction();
import requests
import os
from dotenv import load_dotenv
load_dotenv()
BASE_URL = '{BASE_URL}'
def create_first_transaction():
try:
# Step 1: Authenticate
print('Step 1: Authenticating...')
auth_response = requests.post(
f'{BASE_URL}/api/v4/authorize/',
data={
'partnerId': os.environ['NOTARYCAM_PARTNER_ID'],
'apiKey': os.environ['NOTARYCAM_API_KEY'],
'apiSecret': os.environ['NOTARYCAM_API_SECRET']
},
headers={'Content-Type': 'application/x-www-form-urlencoded'}
)
token = auth_response.json()['token']
print(' Authenticated\n')
headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
# Step 2: Create Users
print('Step 2: Creating users...')
user1 = requests.post(f'{BASE_URL}/api/v4/users', json={
'departments': [os.environ['NOTARYCAM_DEPARTMENT_ID']],
'email': 'john.doe@example.com',
'firstName': 'John',
'lastName': 'Doe',
'phone': '+15551234567',
'dateOfBirth': '1985-06-15T00:00:00.000Z',
'address': {
'country': 'US',
'street': '123 Main St',
'city': 'San Francisco',
'state': 'CA',
'postalCode': '94102'
}
}, headers=headers)
user2 = requests.post(f'{BASE_URL}/api/v4/users', json={
'departments': [os.environ['NOTARYCAM_DEPARTMENT_ID']],
'email': 'jane.smith@example.com',
'firstName': 'Jane',
'lastName': 'Smith',
'phone': '+15559876543',
'dateOfBirth': '1990-03-22T00:00:00.000Z',
'address': {
'country': 'US',
'street': '456 Oak Ave',
'city': 'Austin',
'state': 'TX',
'postalCode': '78701'
}
}, headers=headers)
print(' Created users\n')
# Step 3: Create Transaction
print('Step 3: Creating transaction...')
transaction = requests.post(f'{BASE_URL}/api/v4/transactions/', json={
'department': os.environ['NOTARYCAM_DEPARTMENT_ID'], # Required
'participants': [
{'user': user1.json()['user']['_id'], 'role': 'signer'},
{'user': user2.json()['user']['_id'], 'role': 'signer'}
],
'workflow': os.environ['NOTARYCAM_WORKFLOW_ID']
}, headers=headers)
transaction_id = transaction.json()['transaction']['_id']
print(f' Transaction created: {transaction_id}\n')
# Step 4: Upload Documents
print('Step 4: Uploading documents...')
files = {
'documents': ('sample.pdf', open('./sample.pdf', 'rb'), 'application/pdf')
}
data = {
'documentData': json.dumps([
{'fileName': 'sample.pdf', 'type': 'notarize'}
])
}
requests.post(
f'{BASE_URL}/api/v4/transactions/{transaction_id}/documents',
files=files,
data=data,
headers={'Authorization': headers['Authorization']}
)
print(' Documents uploaded\n')
# Step 5: Set Metadata
print('Step 5: Setting metadata...')
requests.put(
f'{BASE_URL}/api/v4/transactions/{transaction_id}/metadata',
json={
'notes': ['First API transaction'],
'customFields': [{'name': 'Source', 'value': 'API Tutorial'}]
},
headers=headers
)
print(' Metadata set\n')
# Step 6: Activate
print('Step 6: Activating transaction...')
requests.put(
f'{BASE_URL}/api/v4/transactions/{transaction_id}/activate',
json={},
headers=headers
)
print(' Transaction activated\n')
print(f' Complete! Transaction ID: {transaction_id}')
print('\nParticipant Room URLs:')
for i, p in enumerate(transaction.json()['transaction']['participants']):
print(f' {i + 1}. {p["user"]["email"]}: {p["roomURL"]}')
except Exception as error:
print(f' Error: {error}')
exit(1)
if __name__ == '__main__':
create_first_transaction()
Troubleshooting
Common Issues
"Invalid credentials" error?
- Verify your environment variables are set correctly
- Check you're using the right base URL (sandbox vs production)
- Ensure API keys haven't expired
Documents not uploading?
- Verify the document URL is publicly accessible
- Check the file is a PDF
- Ensure file size is under 25MB
Transaction won't activate?
- Ensure at least one document is uploaded
- Verify all required participants are added
- Check that workflow ID is valid
Next Steps
Congratulations! You've created your first NotaryCam transaction. Now explore:
- Webhook Integration - Receive real-time status updates
Need Help?
- Review: Full API Reference
- Support: support@notarycam.com