¿Qué es un Facebook Page-Scoped ID (PSID) y cómo se usa?
25 may 2026
·
12 min de lectura
En esta guía: Qué es un PSID · PSID vs ASID vs IGSID · El principio de aislamiento · Dónde vive el PSID en los payloads de webhook · Enviar mensajes con un PSID · Búsqueda en Graph API · ID Matching API · El caso límite del reseteo del PSID · Indexación en base de datos · Formato normalizado de SocialHook
¿Qué es un Facebook Page-Scoped ID (PSID)?
Un Page-Scoped ID (PSID) es una cadena numérica única que Facebook asigna para representar a un usuario específico en el contexto de una Facebook Page específica. Es la forma en que tu aplicación identifica quién envió un mensaje a través de Facebook Messenger.
Esto es lo que lo distingue de un ID de usuario común:
Un PSID no es el ID real de Facebook del usuario. Los IDs reales de Facebook son internos a los sistemas de Meta.
Un PSID es específico de cada Page. El mismo usuario tiene un PSID diferente por cada Facebook Page con la que interactúa a través de Messenger.
Un PSID es estable para un par usuario-Page dado, hasta que el usuario bloquea y desbloquea tu Page (consulta el caso límite de reseteo más abajo).
Un PSID es opaco: no transporta información intrínseca sobre el usuario. Es solo un identificador de referencia.
En la práctica: cuando un cliente envía un mensaje de Facebook Messenger a tu negocio, su PSID es el identificador que tu aplicación usa para enviar respuestas, consultar su historial y almacenar el registro de su conversación. Es la clave primaria para cualquier usuario de Messenger en tu sistema.
PSID, ASID e IGSID: los tres tipos de ID de usuario de Facebook
Facebook mantiene tres sistemas distintos de IDs con alcance limitado para tres contextos diferentes. Saber con cuál estás trabajando previene toda una categoría de bugs en los que mezclas inadvertidamente identificadores de usuario.
Messenger
Page-Scoped ID (PSID)
Identifica a un usuario en el contexto de una Facebook Page específica. Aparece en los eventos de webhook de Messenger como sender.id. Se usa para enviar mensajes a través de la Send API. Es diferente para cada Page con la que el usuario contacta.
sender.id in webhook
Facebook Login / Social Apps
App-Scoped ID (ASID)
Identifica a un usuario en el contexto de una Facebook App específica. Se devuelve cuando los usuarios inician sesión a través de Facebook Login (OAuth). Es diferente para cada app con la que el usuario se autentica. Se usa en llamadas a la Graph API para apps sociales.
returned by Facebook Login
Instagram DM
Instagram-Scoped ID (IGSID)
Identifica a un usuario en el contexto de una cuenta Instagram Business específica. Aparece en los eventos de webhook de DM de Instagram. Concepto similar al PSID, pero para Instagram. Se usa para enviar respuestas a través de la Instagram Messaging API.
sender.id in IG webhook
Nunca mezcles estos IDs. Intentar enviar un mensaje de Messenger a un ASID devuelve un error. Intentar usar un PSID de una Facebook Page para enviar un mensaje a través de otra Page también falla: los PSIDs están limitados a una Page y solo pueden usarse con el Page Access Token de la Page que los generó. Almacenar distintos tipos de ID en la misma columna de base de datos sin una etiqueta de tipo es un bug común.
El principio de aislamiento: por qué los PSIDs difieren entre Pages
Facebook diseñó el sistema de PSIDs específicamente para impedir el seguimiento de usuarios entre plataformas. Si cada app y operador de Page recibiera el mismo ID de usuario, los corredores de datos y actores maliciosos podrían correlacionar identidades de usuarios entre cientos de negocios diferentes: exactamente ese tipo de recolección de datos entre servicios que condujo al escándalo de Cambridge Analytica.
El aislamiento significa que: si tu negocio opera dos Facebook Pages, el mismo usuario de Facebook tiene PSIDs diferentes en cada una. No puedes usar el PSID de la Page A para consultar actividad en la Page B sin el consentimiento explícito del usuario y la ID Matching API (que se cubre más abajo).
Mismo usuario de Facebook
Alice Johnson (ID real de FB: oculto para ti)
Tu Page principal de la tienda
PSID: 12345678901234
Tu Page de soporte
PSID: 98765432109876
La Page de tu socio
PSID: 11223344556677
Alice tiene tres PSIDs completamente diferentes en tres Pages. No hay correlación posible entre ellos solo a partir de los datos. Es así por diseño, y por eso construir operaciones de Messenger en varias Pages exige pensar con cuidado qué PSID pertenece a qué contexto de Page.
Dónde vive el PSID en los payloads de webhook de Messenger
Cuando un usuario envía un mensaje a tu Facebook Page, la Messenger Platform dispara un HTTP POST a la URL de webhook que tienes registrada. El PSID está en entry[0].messaging[0].sender.id dentro del payload en bruto. Esta es la estructura completa:
Facebook Messenger webhook payload
messenger-webhook.json
{
"object": "page", // always "page" for Messenger webhooks"entry": [{
"id": "PAGE_ID", // your Facebook Page ID (not a PSID)"time": 1747231892123,
"messaging": [{
"sender": {
"id": "12345678901234"// ← THIS IS THE PSID — the user who sent the message
},
"recipient": {
"id": "PAGE_ID"// your Page ID — same as entry.id
},
"timestamp": 1747231892100,
"message": {
"mid": "m_abc123...", // unique message ID"text": "Hello! I need help with my order."
}
}]
}]
}
// PSID extraction path: body.entry[0].messaging[0].sender.id// Page ID path: body.entry[0].id (same as recipient.id)
Extraer el PSID correctamente:
Node.js — PSID extraction from raw webhook
extractPsid.js
app.post('/webhook/facebook', (req, res) => {
res.sendStatus(200); // acknowledge firstconst body = req.body;
if (body.object !== 'page') return;
body.entry.forEach(entry => {
const pageId = entry.id; // your Page ID
entry.messaging.forEach(event => {
const psid = event.sender.id; // ← the PSIDconst pageId = event.recipient.id; // confirms which Page received itif (event.message) {
console.log(`Message from PSID ${psid} on page ${pageId}:`, event.message.text);
handleMessage(psid, pageId, event.message);
} else if (event.postback) {
handlePostback(psid, pageId, event.postback);
} else if (event.read) {
handleRead(psid, event.read.watermark);
}
});
});
});
Enviar mensajes de vuelta usando un PSID
Para responder a un usuario, haces un POST a la Send API usando su PSID como destinatario. El PSID es el único identificador que necesitas: Facebook resuelve el usuario a partir de él y entrega el mensaje en su bandeja de entrada de Messenger.
Node.js — send Messenger message by PSID
sendByPsid.js
constGRAPH = 'https://graph.facebook.com/v21.0';
const PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN; // must match the Page that got the PSIDasync functionsendMessengerMessage(psid, messageText) {
const res = awaitfetch(
`${GRAPH}/me/messages?access_token=${PAGE_ACCESS_TOKEN}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
recipient: { id: psid }, // PSID goes here
message: { text: messageText },
messaging_type: 'RESPONSE', // within 24h window
}),
}
);
if (!res.ok) {
const err = await res.json();
if (err.error?.code === 551 || err.error?.code === 100) {
// PSID may be invalid/reset — user may have blocked and unblockedthrowObject.assign(newError('Invalid PSID'), { code: 'PSID_INVALID', psid });
}
thrownewError(`Messenger send error: ${JSON.stringify(err)}`);
}
returnawait res.json(); // { recipient_id: psid, message_id: "m_..." }
}
// Critical: use the Page Access Token from the Page that the user's PSID belongs to.// Using a different Page's token returns an error even if the PSID format is correct.
Consultar información de usuario vía Graph API usando un PSID
Con un PSID y tu Page Access Token, puedes consultar la Graph API para recuperar la información de perfil público del usuario, en concreto su nombre, apellido y foto de perfil. Esto resulta útil para personalizar las respuestas de tu bot y prepoblar registros de CRM.
Permisos necesarios: tu Facebook App debe tener aprobado el permiso pages_messaging para leer el perfil del usuario vía PSID. Sin él, la Graph API devuelve solo el campo id. Los campos de perfil (nombre, foto) requieren que el usuario haya enviado primero un mensaje explícito a tu Page: no puedes consultar PSIDs arbitrarios, solo los de personas que han iniciado una conversación con tu Page.
Node.js — Graph API user lookup by PSID
lookupByPsid.js
async functiongetUserProfile(psid) {
const fields = 'first_name,last_name,profile_pic,locale,timezone,gender';
const url = `${GRAPH}/${psid}?fields=${fields}&access_token=${PAGE_ACCESS_TOKEN}`;
const res = awaitfetch(url);
if (!res.ok) throw newError(`Profile lookup failed: ${await res.text()}`);
returnawait res.json();
// Returns: { id, first_name, last_name, profile_pic, locale, timezone }
}
// Usage — look up profile on first contact and store itasync functiononFirstContact(psid) {
const profile = awaitgetUserProfile(psid);
awaitupsertUser({
psid,
firstName: profile.first_name,
lastName: profile.last_name,
profilePic: profile.profile_pic,
locale: profile.locale, // e.g. "pt_BR" — useful for language routing
});
}
// Note: gender and timezone fields deprecated by Meta in v18.0+// Stick to first_name, last_name, profile_pic, locale for future-safe code
La ID Matching API: convertir PSID ↔ ASID
En algunos casos puede que necesites correlacionar a un usuario de Messenger (identificado por PSID) con el mismo usuario autenticado vía Facebook Login (identificado por ASID). Facebook proporciona la ID Matching API para esto, pero exige el permiso pages_user_ids Y solo funciona entre aplicaciones que estén bajo el mismo Business Portfolio.
El caso de uso típico: un usuario se autentica con Facebook Login (lo que te da su ASID) y más tarde te contacta por Messenger (lo que te da su PSID). Quieres vincular ambos identificadores al mismo registro de usuario en tu base de datos.
Node.js — ID Matching API (PSID ↔ ASID)
idMatching.js
// Convert PSID → ASID (to find the same user who logged in via Facebook Login)async functiongetAsidFromPsid(psid) {
const url = `${GRAPH}/${psid}?fields=ids_for_apps&access_token=${PAGE_ACCESS_TOKEN}`;
const res = awaitfetch(url);
const data = await res.json();
// Returns array of app-scoped IDs for apps in the same Business Portfolioconst appIds = data.ids_for_apps?.data ?? [];
const match = appIds.find(a => a.app.id === process.env.FB_APP_ID);
return match?.id; // the ASID for this user on your app
}
// Convert ASID → PSID (to find the Messenger identity of a logged-in user)async functiongetPsidFromAsid(asid) {
const url = `${GRAPH}/${asid}?fields=ids_for_pages&access_token=${PAGE_ACCESS_TOKEN}`;
const res = awaitfetch(url);
const data = await res.json();
const pageIds = data.ids_for_pages?.data ?? [];
const match = pageIds.find(p => p.page.id === process.env.FB_PAGE_ID);
return match?.id; // the PSID for this user on your Page
}
// Requirements:// - App must have pages_user_ids permission (requires App Review)// - Both apps must be under the same Business Portfolio// - User must have interacted with both the Page and the App
El caso límite del reseteo de PSID que debes manejar
Hay un escenario en el que el PSID de un usuario cambia: si el usuario bloquea tu Facebook Page y luego la desbloquea. Cuando te desbloquea y vuelve a escribirte, recibe un PSID totalmente nuevo para tu Page. Su PSID antiguo queda huérfano: cualquier mensaje que intentes enviar a él fallará.
Este caso límite es fácil de pasar por alto porque ocurre en silencio. El usuario no sabe que su PSID cambió. Tu base de datos sigue teniendo el PSID antiguo. Cuando intentas enviarle un mensaje, recibes un error. Así es como manejarlo correctamente:
Node.js — PSID reset detection and update
psidReset.js
async functionhandleInboundMessage(event) {
const psid = event.sender.id;
const message = event.message;
// Look up this PSID in your databaselet user = await db.findByPsid(psid);
if (!user) {
// New PSID — either genuinely new user or a PSID reset after block/unblock// Check if we have a user with matching profile (name + profile pic)const profile = awaitgetUserProfile(psid);
const existing = await db.findByProfile(profile.first_name, profile.last_name);
if (existing) {
// Likely a PSID reset — update the stored PSIDawait db.updatePsid(existing.id, psid);
user = { ...existing, psid };
console.log(`PSID reset detected for user ${existing.id} — new PSID: ${psid}`);
} else {
// Genuinely new user
user = await db.createUser({ psid, ...profile });
}
}
awaitprocessMessage(user, message);
}
// Also: subscribe to the messaging_optins and messaging_optouts webhook events// messaging_optouts fires when a user blocks your page — flag the PSID as potentially stale
Indexación en base de datos: la forma correcta de almacenar PSIDs
Los errores al almacenar PSIDs provocan bugs sutiles y difíciles de depurar. Estos son los patrones correctos:
Nunca uses el PSID como clave primaria. Los PSIDs pueden cambiar (escenario de bloqueo/desbloqueo). Usa un auto-incremental interno o un UUID como clave primaria. El PSID es un identificador externo que se mapea a tu usuario interno.
Almacena siempre el Page ID junto con el PSID. Un PSID solo tiene sentido en el contexto de la Page para la que se generó. Si operas varias Pages, (psid, page_id) debe ser una restricción única compuesta, no psid por sí solo.
Indexa la columna del PSID. Cada mensaje entrante requiere una búsqueda por PSID. Sin un índice, esto es un escaneo completo de la tabla en cada evento de webhook.
Almacena el PSID como cadena. Los PSIDs son cadenas numéricas que pueden exceder el rango seguro de enteros de JavaScript (Number.MAX_SAFE_INTEGER). Trátalos siempre como cadenas, no como números.
SQL — correct PSID schema
schema.sql
CREATE TABLE messenger_users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
psid VARCHAR(25) NOT NULL, -- string, not bigint
page_id VARCHAR(25) NOT NULL, -- which Facebook Page generated this PSID
first_name VARCHAR(100),
last_name VARCHAR(100),
profile_pic TEXT,
locale VARCHAR(10), -- e.g. 'pt_BR', 'en_US'
asid VARCHAR(25), -- linked App-Scoped ID (Facebook Login), nullable
is_active BOOLEAN DEFAULT TRUE, -- false if PSID became invalid
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE (psid, page_id) -- composite unique — PSID is page-scoped
);
CREATE INDEX idx_messenger_users_psid ON messenger_users (psid);
CREATE INDEX idx_messenger_users_page_id ON messenger_users (page_id);
CREATE INDEX idx_messenger_users_asid ON messenger_users (asid) WHERE asid IS NOT NULL;
-- Never store PSID as INTEGER or BIGINT-- Example PSID: '1234567890123456789' — exceeds JS Number.MAX_SAFE_INTEGER-- parseInt('1234567890123456789') === 1234567890123456800 — wrong!
El PSID en los eventos normalizados de Facebook Messenger de SocialHook
Cuando usas SocialHook para Facebook Messenger, el PSID viene preextraído del envoltorio del webhook de Messenger en bruto y se entrega en el nivel superior del evento normalizado. No hace falta navegar por la ruta anidada entry[0].messaging[0].sender.id:
SocialHook normalized Facebook Messenger event
{
"platform": "facebook",
"event": "message.received",
"timestamp": 1747231892,
"from": "12345678901234", // ← this IS the PSID, ready to use"page_id": "PAGE_ID", // which Page received the message"conversation_id": "conv_fb_8j3k...",
"message": {
"type": "text",
"body": "Hello! I need help with my order.",
"id": "m_abc123..."
},
"signature_verified": true
}
// event.from === the PSID — same format as WhatsApp's event.from for phone numbers// event.page_id — use this for multi-page routing (PSID is specific to this page)// Same payload structure as WhatsApp and Instagram events — one handler for all channels
La ventaja clave para despliegues multicanal: SocialHook normaliza el PSID (Facebook), el número de teléfono (WhatsApp) y el IGSID (Instagram) en el mismo campo from con la misma forma de payload. El código de tu aplicación puede manejar los tres canales con una sola función de manejo de mensajes, diferenciando por platform cuando haga falta. Consulta la referencia de payload para la comparación de esquemas completa entre los tres canales.
FAQ
Preguntas frecuentes
¿Qué es un Facebook Page-Scoped ID (PSID)?
Un PSID es una cadena opaca y única que Facebook asigna para representar a un usuario específico en el contexto de una Facebook Page concreta. Cuando alguien envía un mensaje de Messenger a tu Facebook Page, Facebook lo identifica ante tu aplicación mediante su PSID, no mediante su ID real de Facebook. La misma persona tiene un PSID diferente por cada Page con la que interactúa, lo que proporciona aislamiento de privacidad entre operadores de Pages.
¿Dónde aparece el PSID en un payload de webhook de Facebook Messenger?
En el webhook en bruto de Messenger: body.entry[0].messaging[0].sender.id. En el formato normalizado de SocialHook: event.from. El sender.id es siempre el PSID de la persona que envió el mensaje. El recipient.id es el ID de tu Page (no un PSID). Cuando iteres varias entries y arrays de messaging, usa siempre messaging[n].sender.id, no entry[n].id.
¿Puede cambiar el PSID de un usuario?
Sí: cuando un usuario bloquea tu Facebook Page y la desbloquea más tarde, recibe un nuevo PSID para tu Page. Su PSID anterior queda inválido. Esto ocurre en silencio. Comprueba siempre los errores PSID_INVALID al enviar mensajes y actualiza tu base de datos cuando recibas un PSID nuevo de un usuario cuyo perfil coincide con un registro existente. Nunca uses el PSID como clave primaria por este motivo.
¿Puedo enviar un mensaje de Messenger a un usuario del que nunca he recibido un mensaje?
No a través de la Send API estándar sin un PSID. Necesitas que el usuario inicie el contacto (lo que te da su PSID) o necesitas obtener su PSID vía la ID Matching API (si ha usado Facebook Login en tu app y tienes el permiso pages_user_ids). No puedes consultar los PSIDs de usuarios arbitrarios: los PSIDs solo existen en el contexto de un usuario que ha interactuado con tu Page específica. Es así por diseño, para proteger la privacidad.
¿Por qué debo almacenar el PSID como cadena y no como entero?
Los PSIDs son cadenas numéricas que pueden exceder el Number.MAX_SAFE_INTEGER de JavaScript (9.007.199.254.740.991). Si analizas un PSID como "1234567890123456789" como entero de JavaScript, obtienes pérdida de precisión: parseInt('1234567890123456789') === 1234567890123456800: los últimos dígitos están mal. Almacena y pasa siempre los PSIDs como cadenas en tu base de datos (VARCHAR/TEXT) y en tu código. Nunca los conviertas a números.
¿En qué se diferencia el PSID del ASID?
El PSID (Page-Scoped ID) es para Messenger: identifica a un usuario por Facebook Page. El ASID (App-Scoped ID) es para Facebook Login: identifica a un usuario por Facebook App. El mismo usuario tiene un PSID diferente para cada Page y un ASID diferente para cada App. Puedes convertir entre ellos usando la ID Matching API, pero solo si tanto la Page como la App están bajo el mismo Business Portfolio y tienes el permiso pages_user_ids.
Conecta tu Facebook Page a SocialHook y recibe cada evento de Messenger con el PSID preextraído en event.from, junto a tus eventos de WhatsApp e Instagram en el mismo formato normalizado. Un solo handler para los tres canales.