API de Dynamics 365 CRM
Lee y escribe en Dynamics 365 CRM (Dataverse) con la API pública de Plur-e — las 13 operaciones con ejemplos curl, el select obligatorio, la paginación por cursor y cómo se acotan borrados y acciones.
Respuesta rápida
La API de CRM expone 13 operaciones bajo /crm: listar y describir entidades, consultar y leer
registros, crear, actualizar, eliminar, cambiar estado, asignar, asociar, FetchXML, búsqueda y
acciones personalizadas. Leer exige crm:read, crear/actualizar crm:write y eliminar
crm:delete. Las consultas deben pasar select, los resultados se paginan con
nextCursor y cada llamada se ejecuta como el usuario de aplicación de la conexión de CRM
ligada a la clave, limitada por los roles de CRM de la clave.
URL base: https://api.plur-e.com/api/public/v1. Los nombres en la ruta son los nombres de entity
set de Dataverse (en plural, por ejemplo accounts, contacts). Las columnas de opciones son
enteros y los lookups se leen como _<columna>_value. Si no hay un CRM conectado, la llamada responde
409 con el código crm_not_connected.
Las 13 operaciones
| Operación | Método y ruta | Scope |
|---|---|---|
| Listar entidades | GET /crm/entities?search= | crm:read |
| Describir una entidad | GET /crm/entities/{entitySet} | crm:read |
| Consultar registros | GET /crm/records/{entitySet} | crm:read |
| Leer un registro | GET /crm/records/{entitySet}/{id} | crm:read |
| Crear un registro | POST /crm/records/{entitySet} | crm:write |
| Actualizar un registro | PATCH /crm/records/{entitySet}/{id} | crm:write |
| Eliminar un registro | DELETE /crm/records/{entitySet}/{id} | crm:delete |
| Cambiar estado | POST /crm/records/{entitySet}/{id}/state | crm:write |
| Asignar | POST /crm/records/{entitySet}/{id}/assign | crm:write |
| Asociar o desasociar | POST /crm/records/{entitySet}/{id}/associate | crm:write (crm:delete para desasociar) |
| FetchXML | POST /crm/fetchxml | crm:read |
| Buscar | GET /crm/search?text=&entities=&top= | crm:read |
| Ejecutar una acción | POST /crm/actions/{action} | crm:write (crm:delete para acciones de tipo borrado) |
Cada llamada se comprueba además contra los roles de CRM de la clave: la entidad necesita Read, New,
Update o Delete allí, según la operación. Una llamada que los roles no conceden responde 403.
Leer
# ¿Qué entidades puede ver esta clave?
curl -s "https://api.plur-e.com/api/public/v1/crm/entities?search=account" \
-H "Authorization: Bearer <YOUR_API_KEY>"
# Columnas y relaciones de una entidad
curl -s "https://api.plur-e.com/api/public/v1/crm/entities/accounts" \
-H "Authorization: Bearer <YOUR_API_KEY>"Describe una entidad antes de consultarla: nunca adivines nombres de columna.
Consultar registros
curl -s -G "https://api.plur-e.com/api/public/v1/crm/records/accounts" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
--data-urlencode "select=name,accountnumber" \
--data-urlencode "filter=statecode eq 0" \
--data-urlencode "orderBy=name asc" \
--data-urlencode "pageSize=50" \
--data-urlencode "count=true"| Parámetro de consulta | Significado |
|---|---|
select | Obligatorio (salvo que pases un cursor): nombres de columna separados por comas. Sin él la llamada responde 400 con el código crm_invalid_query |
filter | $filter de OData |
orderBy | Columnas con asc / desc opcional |
expand | Registros relacionados a incluir |
pageSize | Filas por página |
cursor | El nextCursor de la página anterior |
count | true añade el total de filas que cumplen la consulta |
Sigue nextCursor hasta que venga vacío. Mantén las páginas pequeñas.
curl -s -G "https://api.plur-e.com/api/public/v1/crm/records/accounts/<RECORD_ID>" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
--data-urlencode "select=name,accountnumber"FetchXML y búsqueda
curl -s -X POST "https://api.plur-e.com/api/public/v1/crm/fetchxml" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{ "entitySet": "accounts", "fetchXml": "<fetch top=\"10\"><entity name=\"account\"><attribute name=\"name\"/></entity></fetch>", "cursor": null }'
curl -s -G "https://api.plur-e.com/api/public/v1/crm/search" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
--data-urlencode "text=contoso" \
--data-urlencode "entities=accounts,contacts" \
--data-urlencode "top=10"Cada tabla unida en una consulta FetchXML necesita también Read en los roles de la clave.
Escribir
Crear, actualizar y eliminar devuelven el objeto que devuelve la operación de CRM. Crear responde
201; las demás responden 200.
# Crear (values son columnas; lookups enlaza un registro relacionado por id)
curl -s -X POST "https://api.plur-e.com/api/public/v1/crm/records/contacts" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{ "values": { "firstname": "Ada", "lastname": "Lovelace" }, "lookups": { "parentcustomerid_account": "<ACCOUNT_ID>" } }'
# Actualizar (clearLookups quita lookups; etag protege frente a ediciones concurrentes)
curl -s -X PATCH "https://api.plur-e.com/api/public/v1/crm/records/contacts/<RECORD_ID>" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{ "values": { "jobtitle": "Engineer" }, "lookups": { }, "clearLookups": [ ], "etag": null }'
# Eliminar (necesita crm:delete)
curl -s -X DELETE "https://api.plur-e.com/api/public/v1/crm/records/contacts/<RECORD_ID>" \
-H "Authorization: Bearer <YOUR_API_KEY>"| Operación | Cuerpo |
|---|---|
| Crear | { "values": { }, "lookups": { } } |
| Actualizar | { "values": { }, "lookups": { }, "clearLookups": [ ], "etag": "…" } |
| Cambiar estado | { "stateCode": 1, "statusCode": 2 } |
| Asignar | { "ownerType": "systemuser" o "team", "ownerId": "…" } |
| Asociar | { "navigation": "…", "relatedEntitySet": "…", "relatedId": "…", "remove": false } |
| Ejecutar una acción | { "parameters": { }, "boundEntitySet": "…", "boundId": "…" } (los campos bound solo en una acción bound) |
curl -s -X POST "https://api.plur-e.com/api/public/v1/crm/records/accounts/<RECORD_ID>/state" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{ "stateCode": 1, "statusCode": 2 }'Qué necesita crm:delete
DELETE /crm/records/{entitySet}/{id}.- Desasociar: una llamada
associatecon"remove": true. Asociar sinremovesolo necesitacrm:write. - Acciones con nombre de tipo borrado: una acción cuyo nombre contenga
deleteoremove(con cualquier combinación de mayúsculas) necesitacrm:deleteademás decrm:write, porque las acciones personalizadas pueden borrar datos aunque se ejecuten con permisos de actualización.
Sin el scope adicional, la llamada responde 403 con el error plure_1321 y el mensaje
This API key does not have the scope 'crm:delete'.
Como quién se ejecuta la llamada
Las llamadas de CRM se ejecutan como el usuario de aplicación de la conexión, no como una
persona. Lo que puede hacer está limitado de tres formas: por los scopes de la clave, por los roles de
CRM de la clave y por los roles de seguridad del usuario de aplicación en Dynamics 365. Un rechazo del
propio Dataverse responde 403 con el código crm_privilege.
Códigos de error de CRM
| Código | HTTP | Significado |
|---|---|---|
crm_invalid_query | 400 | Se rompe una regla de la consulta, por ejemplo falta select |
crm_not_found | 404 | La entidad o el registro no existe |
crm_privilege | 403 | El usuario de aplicación no tiene el privilegio en Dynamics 365 |
crm_duplicate | 409 | Dataverse detectó un duplicado |
crm_not_connected | 409 | El tenant no tiene un CRM conectado |
Consulta Errores para la lista completa.
API de Business Central
Llama a Business Central con la API pública de Plur-e — listar y ejecutar métodos catalogados, consultas OData de solo lectura, el scope de cada llamada y los borrados que la API rechaza siempre.
API del panel de Plur-e
Lee los usuarios móviles, dispositivos, ubicaciones registradas, actividad, roles y módulos licenciados de Plur-e con la API pública — las ocho rutas de solo lectura, sus scopes, paginación y campos.