Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,45 @@ await ccai.contact.setDoNotText(false, undefined, '+15551234567');
await ccai.contact.setDoNotText(true, 'contact-abc-123');
```

### Contact Validator

Validate email addresses and phone numbers.

> Bulk endpoints accept up to 50 contacts per request and are processed server-side in chunks.

```typescript
import { CCAI } from 'ccai-node';

const ccai = new CCAI({
clientId: 'YOUR-CLIENT-ID',
apiKey: 'YOUR-API-KEY'
});

// Validate a single email
const emailResult = await ccai.contactValidator.validateEmail('user@example.com');
console.log(emailResult.status); // "valid" | "invalid" | "risky"
console.log(emailResult.metadata.safe_to_send); // true | false

// Validate multiple emails (up to 50, processed server-side in chunks)
const bulkEmails = await ccai.contactValidator.validateEmails([
'user@example.com',
'invalid@nonexistent.xyz'
]);
console.log(bulkEmails.summary); // { total: 2, valid: 1, invalid: 1, risky: 0 }

// Validate a single phone number
const phoneResult = await ccai.contactValidator.validatePhone('+15551234567', 'US');
console.log(phoneResult.status); // "valid" | "invalid" | "landline"
console.log(phoneResult.metadata.carrier_type); // "mobile" | "landline" | "voip"

// Validate multiple phone numbers (up to 50, processed server-side in chunks)
const bulkPhones = await ccai.contactValidator.validatePhones([
{ phone: '+15551234567' },
{ phone: '+15559876543', countryCode: 'US' }
]);
console.log(bulkPhones.summary); // { total: 2, valid: 1, invalid: 0, risky: 0, landline: 1 }
```

### Webhooks

CloudContactAI can send webhook notifications when certain events occur, such as when messages are sent or received. Use the Webhook service to register, manage, and verify webhooks programmatically.
Expand Down Expand Up @@ -704,6 +743,7 @@ This project includes a `.gitignore` file that excludes:
- Brand registration and management for TCR verification
- Campaign registration and management for TCR carrier vetting
- Manage contact opt-out preferences (setDoNotText)
- Validate email addresses (valid/invalid/risky) and phone numbers (valid/invalid/landline)
- Webhook management: register, list, update, delete
- Webhook signature verification (HMAC-SHA256)
- Next.js API route handlers for webhook events
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ccai-node",
"version": "1.0.2",
"version": "1.1.0",
"description": "TypeScript client for CloudContactAI API",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
5 changes: 5 additions & 0 deletions src/ccai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import axios, { AxiosResponse } from 'axios';
import { Brands } from './brands/brands';
import { Campaigns } from './campaigns/campaigns';
import { ContactValidator } from './contact-validator/contact-validator';
import { Contact } from './contact/contact';
import { Email } from './email/email';
import { MMS } from './sms/mms';
Expand Down Expand Up @@ -110,6 +111,9 @@ export class CCAI {
/** Contact service for managing contact preferences */
public contact: Contact;

/** Contact validator service for validating emails and phone numbers */
public contactValidator: ContactValidator;

/**
* Create a new CCAI client instance
* @param config - Configuration object
Expand Down Expand Up @@ -159,6 +163,7 @@ export class CCAI {
this.contact = new Contact(this);
this.brands = new Brands(this);
this.campaigns = new Campaigns(this);
this.contactValidator = new ContactValidator(this);
}

/**
Expand Down
117 changes: 117 additions & 0 deletions src/contact-validator/contact-validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* contact-validator.ts - A TypeScript module for validating email and phone contacts via CloudContactAI
*
* @license MIT
* @copyright 2025 CloudContactAI LLC
*/

import { CCAI } from '../ccai';

export type ValidationStatus = 'valid' | 'invalid' | 'risky' | 'landline';

export type EmailValidationMetadata = {
safe_to_send?: boolean;
ai_verdict?: string | null;
[key: string]: unknown;
};

export type PhoneValidationMetadata = {
country_code?: string | null;
national_number?: string | null;
carrier_type?: string | null;
[key: string]: unknown;
};

export type EmailValidationResult = {
contactField: string;
type: 'email';
status: ValidationStatus;
metadata: EmailValidationMetadata;
};

export type PhoneValidationResult = {
contactField: string;
type: 'phone';
status: ValidationStatus;
metadata: PhoneValidationMetadata;
};

export type ValidationSummary = {
total: number;
valid: number;
invalid: number;
risky: number;
landline?: number;
};

export type BulkEmailValidationResult = {
results: EmailValidationResult[];
summary: ValidationSummary;
};

export type BulkPhoneValidationResult = {
results: PhoneValidationResult[];
summary: ValidationSummary;
};

export type PhoneInput = {
phone: string;
countryCode?: string;
};

/**
* Service for validating email addresses and phone numbers
*/
export class ContactValidator {
private ccai: CCAI;

constructor(ccai: CCAI) {
this.ccai = ccai;
}

/**
* Validate a single email address
* @param email - Email address to validate
* @returns Promise resolving to the validation result
*/
validateEmail(email: string): Promise<EmailValidationResult> {
return this.ccai.request<EmailValidationResult>('POST', '/v1/contact-validator/email', {
email,
});
}

/**
* Validate multiple email addresses (up to 50)
* @param emails - List of email addresses to validate
* @returns Promise resolving to bulk validation results with summary
*/
validateEmails(emails: string[]): Promise<BulkEmailValidationResult> {
return this.ccai.request<BulkEmailValidationResult>('POST', '/v1/contact-validator/emails', {
emails,
});
}

/**
* Validate a single phone number
* @param phone - Phone number in E.164 format (e.g. +15551234567)
* @param countryCode - Optional ISO 3166-1 alpha-2 country code (e.g. "US")
* @returns Promise resolving to the validation result
*/
validatePhone(phone: string, countryCode?: string): Promise<PhoneValidationResult> {
return this.ccai.request<PhoneValidationResult>('POST', '/v1/contact-validator/phone', {
phone,
countryCode,
});
}

/**
* Validate multiple phone numbers (up to 50)
* @param phones - List of phone inputs with optional country codes
* @returns Promise resolving to bulk validation results with summary
*/
validatePhones(phones: PhoneInput[]): Promise<BulkPhoneValidationResult> {
return this.ccai.request<BulkPhoneValidationResult>('POST', '/v1/contact-validator/phones', {
phones,
});
}
}
22 changes: 22 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ import { Campaigns } from './campaigns/campaigns';
import type { CampaignData, CampaignResponse } from './campaigns/campaigns';
import { CCAI } from './ccai';
import type { Account, CCAIConfig } from './ccai';
import { ContactValidator } from './contact-validator/contact-validator';
import type {
BulkEmailValidationResult,
BulkPhoneValidationResult,
EmailValidationMetadata,
EmailValidationResult,
PhoneInput,
PhoneValidationMetadata,
PhoneValidationResult,
ValidationStatus,
ValidationSummary,
} from './contact-validator/contact-validator';
import { Contact } from './contact/contact';
import type { SetDoNotTextResponse } from './contact/contact';
import { Email } from './email/email';
Expand All @@ -35,6 +47,7 @@ export {
WebhookEventType,
createWebhookHandler,
Contact,
ContactValidator,
Brands,
Campaigns,
};
Expand All @@ -59,4 +72,13 @@ export type {
BrandResponse,
CampaignData,
CampaignResponse,
ValidationStatus,
ValidationSummary,
EmailValidationResult,
EmailValidationMetadata,
PhoneValidationResult,
PhoneValidationMetadata,
BulkEmailValidationResult,
BulkPhoneValidationResult,
PhoneInput,
};
Loading