Facebook Accounts & Pages
The Facebook integration provides endpoints to access Ad Accounts, Business Managers, Facebook Pages, and Lead Forms for campaign management and lead generation.
Endpoints Overview
| Endpoint | Method | Purpose | Source Required |
|---|---|---|---|
/v1/e/facebook/accounts/pages | GET | List Facebook Pages | facebook-leads or reputation |
/v1/e/facebook/accounts/managers | GET | List Business Managers | meta-ads |
/v1/e/facebook/accounts/adaccounts | GET | List Ad Accounts | meta-ads |
/v1/e/facebook/accounts/:pageid/leadforms | GET | Get Lead Forms from Page | facebook-leads |
/v1/e/facebook/accounts/webhook | POST | Create Lead Generation Webhook | facebook-leads |
Ad Account Management
Get Business Managers
Lists all Business Manager accounts accessible by the authenticated user.
Endpoint: GET /v1/e/facebook/accounts/managers
Headers:
Authorization: Bearer <jwt_token>
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id | String | No | Sub-account ID (for agency scenarios) |
Example Request:
GET /v1/e/facebook/accounts/managers
Authorization: Bearer eyJhbGc...
Response:
{
"success": true,
"message": "SUCCESS",
"data": [
{
"id": "123456789",
"name": "My Business Manager",
"created_time": "2023-01-15T10:30:00+0000",
"timezone_id": 1,
"link": "https://business.facebook.com/settings/ad-accounts/123456789"
}
]
}
Business Manager Fields:
const fields = [
'id', // Business Manager ID
'name', // Business name
'created_time', // Creation timestamp
'timezone_id', // Timezone setting
'link', // Direct link to settings
];
Implementation Details:
exports.getAdManagers = async (req, res, next) => {
try {
let accountId = await checkAccountAccess(req);
const existKeys = await facebookModel.find({
accountID: accountId.toString(),
source: 'meta-ads',
});
if (!existKeys) {
return res.status(400).json({
success: false,
errno: 400,
message: 'Record Not found!',
});
}
// Check and refresh token if expired
let accessToken = await facebookModel.checkAccessTokenValidity({
req: req,
expirationTime: existKeys.token.expires_in,
accessToken: existKeys.token.access_token,
docId: existKeys.docId,
source: 'meta-ads',
});
let filterParams = req.query;
let accountsList = await fbProvider.getAdManagers(accessToken, filterParams);
return res.status(200).json({
success: true,
message: 'SUCCESS',
data: accountsList,
});
} catch (error) {
next(error);
}
};
Get Ad Accounts
Lists all Ad Accounts accessible by the authenticated user, with pagination support.
Endpoint: GET /v1/e/facebook/accounts/adaccounts
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id | String | No | Sub-account ID |
limit | Number | No | Results per page (default: 25, max: 100) |
after | String | No | Pagination cursor from previous response |
Example Request:
GET /v1/e/facebook/accounts/adaccounts?limit=50
Authorization: Bearer eyJhbGc...
Response:
{
"success": true,
"message": "SUCCESS",
"data": [
{
"id": "act_123456789",
"account_id": "123456789",
"name": "My Ad Account",
"account_status": 1,
"currency": "USD",
"timezone_name": "America/Los_Angeles",
"timezone_offset_hours_utc": -8,
"business": {
"id": "987654321",
"name": "Business Manager Name"
},
"funding_source_details": {
"type": 1,
"display_string": "•••• 1234"
},
"amount_spent": "12500",
"spend_cap": "50000"
}
],
"paging": {
"cursors": {
"before": "MAZDZD",
"after": "MjQZD"
},
"next": "https://graph.facebook.com/v18.0/me/adaccounts?after=MjQZD"
}
}
Ad Account Fields:
const fields = [
'id', // Ad Account ID (with act_ prefix)
'account_id', // Numeric ID
'name', // Account name
'account_status', // 1=ACTIVE, 2=DISABLED, 3=UNSETTLED
'currency', // Currency code (USD, EUR, etc.)
'timezone_name', // Timezone name
'timezone_offset_hours_utc', // UTC offset
'business', // Parent Business Manager
'funding_source_details', // Payment method info
'amount_spent', // Total spend (cents)
'spend_cap', // Spending limit (cents)
'balance', // Account balance
'disable_reason', // If account disabled
];
Account Status Values:
const accountStatuses = {
1: 'ACTIVE', // Account is active
2: 'DISABLED', // Account disabled
3: 'UNSETTLED', // Payment issues
7: 'PENDING_RISK_REVIEW',
8: 'PENDING_SETTLEMENT',
9: 'IN_GRACE_PERIOD',
100: 'PENDING_CLOSURE',
101: 'CLOSED',
201: 'ANY_ACTIVE',
202: 'ANY_CLOSED',
};
Implementation Details:
exports.getAdAccounts = async (req, res, next) => {
try {
let accountId = await checkAccountAccess(req);
const existKeys = await facebookModel.find({
accountID: accountId.toString(),
source: 'meta-ads',
});
if (!existKeys) {
return res.status(400).json({
success: false,
errno: 400,
message: 'Record Not found!',
});
}
let accessToken = await facebookModel.checkAccessTokenValidity({
req: req,
expirationTime: existKeys.token.expires_in,
accessToken: existKeys.token.access_token,
docId: existKeys.docId,
source: 'meta-ads',
});
let filterParams = req.query;
const { data, paging } = await fbProvider.getAdAccounts(accessToken, filterParams);
return res.status(200).json({
success: true,
message: 'SUCCESS',
data,
paging, // Return pagination info
});
} catch (error) {
next(error);
}
};
Pagination Example:
// First page
GET /v1/e/facebook/accounts/adaccounts?limit=25
// Next page (use 'after' cursor from previous response)
GET /v1/e/facebook/accounts/adaccounts?limit=25&after=MjQZD
// Previous page (use 'before' cursor)
GET /v1/e/facebook/accounts/adaccounts?limit=25&before=MAZDZD
Facebook Pages
Get Facebook Pages
Lists all Facebook Pages managed by the authenticated user. Used for lead generation and reputation management.
Endpoint: GET /v1/e/facebook/accounts/pages
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
source | String | Yes | facebook-leads or reputation |
account_id | String | No | Sub-account ID |
limit | Number | No | Results per page (default: 25) |
after | String | No | Pagination cursor |
Example Request:
GET /v1/e/facebook/accounts/pages?source=facebook-leads&limit=50
Authorization: Bearer eyJhbGc...
Response:
{
"success": true,
"message": "SUCCESS",
"data": [
{
"id": "123456789012345",
"name": "My Business Page",
"access_token": "EAAxxxxxxxx...",
"category": "Local Business",
"category_list": [
{
"id": "2500",
"name": "Local Business"
}
],
"tasks": ["ANALYZE", "ADVERTISE", "MODERATE", "CREATE_CONTENT", "MANAGE"],
"link": "https://www.facebook.com/mybusinesspage",
"fan_count": 1250,
"verification_status": "not_verified"
}
],
"paging": {
"cursors": {
"before": "QVFIUzRJ...",
"after": "QVFIUjVB..."
}
}
}
Page Fields:
const fields = [
'id', // Page ID
'name', // Page name
'access_token', // Page access token
'category', // Primary category
'category_list', // All categories
'tasks', // User permissions on page
'link', // Page URL
'fan_count', // Number of followers
'verification_status', // Verification badge status
'about', // Page description
'phone', // Contact phone
'emails', // Contact emails
'location', // Physical address
];
Page Tasks (Permissions):
const tasks = [
'ANALYZE', // View insights
'ADVERTISE', // Create ads
'MODERATE', // Moderate comments/posts
'CREATE_CONTENT', // Publish content
'MANAGE', // Full page management
];
Implementation Details:
exports.getAccountPages = async (req, res, next) => {
try {
let accountId = await checkAccountAccess(req);
const source = req.query.source;
if (!accountId) {
return res.status(400).json({
success: false,
errno: 400,
message: 'Invalid Account Id',
});
}
const options = {
accountID: accountId.toString(),
source: source,
};
const existKeys = await facebookModel.find(options);
if (!existKeys) {
return res.status(400).json({
success: false,
errno: 400,
message: 'Record Not found!',
});
}
let accessToken = await facebookModel.checkAccessTokenValidity({
req: req,
expirationTime: existKeys.token.expires_in,
accessToken: existKeys.token.access_token,
docId: existKeys.docId,
source: existKeys.source,
});
let filterParams = req.query;
filterParams.access_token = existKeys.token.access_token;
let accountsList = await fbProvider.getAllAccountPages(accessToken, filterParams);
return res.status(200).json({
success: true,
message: 'SUCCESS',
...accountsList,
});
} catch (error) {
next(error);
}
};
Lead Forms
Get Lead Forms from Page
Retrieves all Lead Ad forms configured on a specific Facebook Page.
Endpoint: GET /v1/e/facebook/accounts/:pageid/leadforms
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
pageid | String | Yes | Facebook Page ID |
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
pageaccesstoken | String | Yes | Page-specific access token |
account_id | String | No | Sub-account ID |
Example Request:
GET /v1/e/facebook/accounts/123456789012345/leadforms?pageaccesstoken=EAAxxxxxxxx
Authorization: Bearer eyJhbGc...
Response:
{
"success": true,
"message": "SUCCESS",
"data": [
{
"id": "987654321",
"name": "Contact Us Form",
"status": "ACTIVE",
"locale": "en_US",
"questions": [
{
"key": "FULL_NAME",
"label": "Full Name",
"type": "FULL_NAME"
},
{
"key": "EMAIL",
"label": "Email",
"type": "EMAIL"
},
{
"key": "PHONE_NUMBER",
"label": "Phone",
"type": "PHONE_NUMBER"
},
{
"key": "custom_question_1",
"label": "What service are you interested in?",
"type": "CUSTOM"
}
],
"privacy_policy": {
"url": "https://example.com/privacy",
"link_text": "Privacy Policy"
},
"follow_up_action_url": "https://example.com/thank-you",
"created_time": "2024-01-15T10:30:00+0000",
"page_id": "123456789012345"
}
]
}
Lead Form Fields:
const fields = [
'id', // Form ID
'name', // Form name
'status', // ACTIVE, ARCHIVED, DELETED
'locale', // Language (en_US, es_ES, etc.)
'questions', // Form questions array
'privacy_policy', // Privacy policy link
'follow_up_action_url', // Thank you page URL
'created_time', // Creation timestamp
'page_id', // Parent page ID
];
Question Types:
const questionTypes = {
// Standard fields
FULL_NAME: 'Full name',
FIRST_NAME: 'First name',
LAST_NAME: 'Last name',
EMAIL: 'Email address',
PHONE_NUMBER: 'Phone number',
ZIP_CODE: 'ZIP/Postal code',
CITY: 'City',
STATE: 'State/Province',
COUNTRY: 'Country',
DATE_OF_BIRTH: 'Date of birth',
GENDER: 'Gender',
POST_CODE: 'Post code',
STREET_ADDRESS: 'Street address',
WORK_EMAIL: 'Work email',
WORK_PHONE_NUMBER: 'Work phone',
COMPANY_NAME: 'Company name',
JOB_TITLE: 'Job title',
// Custom fields
CUSTOM: 'Custom question',
CUSTOM_QUESTION: 'Custom question with options',
};
Implementation Details:
exports.getLeadsFormsFromPage = async (req, res, next) => {
try {
let accountId = await checkAccountAccess(req);
if (!accountId) {
return res.status(400).json({
success: false,
errno: 400,
message: 'Invalid Account Id',
});
}
const existKeys = await facebookModel.find({
accountID: accountId.toString(),
source: 'facebook-leads',
});
if (!existKeys) {
return res.status(400).json({
success: false,
errno: 400,
message: 'Record Not found!',
});
}
let fbPageId = req.params.pageid;
let pageAccessToken = req.query.pageaccesstoken;
let filterParams = req.query;
let leadsList = await fbProvider.getAllLeadFormsFromPages(
fbPageId,
pageAccessToken,
filterParams,
);
return res.status(200).json({
success: true,
message: 'SUCCESS',
data: leadsList,
});
} catch (error) {
next(error);
}
};
Webhooks
Create Lead Generation Webhook
Registers a webhook to receive real-time notifications when leads are submitted through Facebook Lead Ads.
Endpoint: POST /v1/e/facebook/accounts/webhook
Headers:
Authorization: Bearer <jwt_token>
Content-Type: application/json
Request Body:
{
"campaign_id": "507f1f77bcf86cd799439011"
}
Body Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
campaign_id | String | Yes | DashClicks campaign ID (MongoDB ObjectId) |
Example Request:
POST /v1/e/facebook/accounts/webhook
Authorization: Bearer eyJhbGc...
Content-Type: application/json
{
"campaign_id": "507f1f77bcf86cd799439011"
}
Response:
{
"success": true,
"data": {
"_id": "60d21b4667d0d8992e610c85",
"account_id": "507f191e810c19729de860ea",
"owner": "507f1f77bcf86cd799439011",
"webhook_url": "https://api.dashclicks.com/webhooks/facebook/leads"
}
}
Webhook Registration Process:
sequenceDiagram
participant API as DashClicks API
participant DB as MongoDB
participant FB as Facebook API
participant Page as Facebook Page
API->>DB: Find campaign by campaign_id
API->>DB: Get facebook-leads token
API->>FB: Get page access token
FB->>API: Return page token
API->>FB: Install app to page
FB->>Page: App installed
API->>FB: Create/update webhook subscription
FB->>API: Webhook created
API->>DB: Save webhook record
API->>API: Return success
Webhook Configuration:
const webhookConfig = {
object: 'page', // Subscribe to page events
callback_url: process.env.FACEBOOK_ADS_WEBHOOK_URL, // Your webhook endpoint
fields: 'leadgen', // Subscribe to lead generation
include_values: true, // Include lead data
verify_token: process.env.FACEBOOK_VERIFY_TOKEN, // Verification token
};
Implementation Details:
exports.createWebhook = async (req, res, next) => {
try {
const appAccessToken = await fbProvider.getAppAccessToken();
let accountId = await checkAccountAccess(req);
if (!accountId) {
return res.status(400).json({
success: false,
errno: 400,
message: 'Invalid Account Id',
});
}
let owner = req.auth.uid.toString();
let campaignId = req.body.campaign_id;
// Build webhook request
let reqBody = {
object: 'page',
callback_url: `${process.env.FACEBOOK_ADS_WEBHOOK_URL}`,
fields: 'leadgen',
include_values: true,
verify_token: `${process.env.FACEBOOK_VERIFY_TOKEN}`,
};
// Get campaign data
let campaignData = await campaignModel.find({ _id: campaignId }).lean().exec();
if (!campaignData || !campaignData[0]) {
return res.status(200).json({ success: true });
}
campaignData = campaignData[0];
// Get Facebook token
const existKeys = await facebookModel.find({
accountID: accountId.toString(),
source: 'facebook-leads',
});
if (!existKeys) {
return res.status(400).json({
success: false,
errno: 400,
message: 'Record Not found!',
});
}
// Validate and refresh token
let accessToken = await facebookModel.checkAccessTokenValidity({
req: req,
expirationTime: existKeys.token.expires_in,
accessToken: existKeys.token.access_token,
docId: existKeys.docId,
source: 'facebook-leads',
});
// Get page access token
let pageAccessToken = await fbProvider.getPageAccessToken(
accessToken,
campaignData.page_id,
'access_token,name,id',
);
// Install app to page
await fbProvider.installApptoPage(campaignData.page_id, pageAccessToken.access_token);
// Create webhook subscription
await fbProvider.createWebhook(appAccessToken.access_token, reqBody);
// Save webhook record
let fbwebhookData = {
account_id: accountId,
owner: owner,
webhook_url: reqBody.callback_url,
};
const readwebHookData = await new fbwebhookModel(fbwebhookData).save();
return res.status(200).json({
success: true,
data: readwebHookData,
});
} catch (error) {
if (error) {
if (error?.response?.data?.error?.message) {
error.additional_info = error.response.data.error.message;
} else if (error?.message) {
error.additional_info = error.message;
}
error.message = 'ERROR_CREATING_WEBHOOK';
}
next(error);
}
};
Webhook Verification:
When Facebook first contacts your webhook endpoint, it sends a verification request:
GET /webhooks/facebook/leads?
hub.mode=subscribe&
hub.challenge=1234567890&
hub.verify_token=your_verify_token
Your endpoint must respond with the hub.challenge value if hub.verify_token matches.
Webhook Payload Example:
When a lead is submitted, Facebook sends:
{
"object": "page",
"entry": [
{
"id": "123456789012345",
"time": 1704844800,
"changes": [
{
"field": "leadgen",
"value": {
"leadgen_id": "987654321",
"page_id": "123456789012345",
"form_id": "555555555",
"adgroup_id": "444444444",
"ad_id": "333333333",
"created_time": 1704844800
}
}
]
}
]
}
Error Handling
Common Errors
// Missing token
{
"success": false,
"errno": 400,
"message": "Record Not found!"
}
// Invalid account access
{
"success": false,
"errno": 400,
"message": "Invalid Account Id"
}
// Token invalidated
{
"success": false,
"errno": 400,
"message": "TOKEN_INVALIDATED",
"additional_info": "Error validating access token"
}
// Webhook creation error
{
"success": false,
"errno": 400,
"message": "ERROR_CREATING_WEBHOOK",
"additional_info": "App not installed on page"
}
Integration Checklist
Ad Account Setup
- Connect Facebook integration with
meta-adssource - Verify access to Business Manager (if applicable)
- Confirm Ad Account permissions
- Test Ad Account listing
- Verify currency and timezone settings
Lead Generation Setup
- Connect Facebook integration with
facebook-leadssource - List Facebook Pages with proper permissions
- Verify page access tokens
- Create lead forms on Facebook
- Create DashClicks campaign
- Register webhook for campaign
- Test webhook delivery
- Verify lead data capture
Monitoring
- Monitor webhook delivery success rate
- Track token expiration and refresh
- Alert on OAuth errors
- Measure page connection stability
Related Documentation
- Facebook Index - Integration overview
- Authentication - OAuth flow and token management
- Campaigns - Campaign operations
- Analytics & Insights - Performance metrics
- Lead Generation - Complete webhook implementation