Ganar o perder oportunidad
https://api.afer.pro/api/v1/crm/opportunities/{id}/close
POST https://api.afer.pro/cerrarOportunidad
Marca una oportunidad como ganada o perdida (con motivo y comentarios), o la reabre.
Cierra el ciclo comercial desde tu aplicación, con la misma semántica que el funnel de Afer:
— ganado: la oportunidad pasa a ganada y se sella la fecha de cierre.
— perdido: pasa a perdida con su fecha, y opcionalmente el motivo (de listarMotivosPerdida) y un comentario libre.
— abierta: reabre la oportunidad (quita ganada/perdida y borra la fecha de cierre).
Puedes fijar el valor_cierre en la misma llamada, que es lo habitual al ganar: ese importe es el que alimenta el win rate y los valores de consultarCRM.
Envía tus claves API en las cabeceras X-API-KEY y X-API-SECRET. La cuenta sobre la que se opera se resuelve automáticamente a partir de la clave. Cómo obtener tus claves →
Este endpoint requiere autenticación con API key: sin credenciales responde 401.
Parámetros del cuerpo
El cuerpo de la petición es un objeto JSON con Content-Type: application/json.
oportunidadIdstring|intobligatorio | Oportunidad a cerrar: id cifrado o numérico legacy. Debe pertenecer a tu cuenta. |
resultadostringobligatorio | "ganado", "perdido" o "abierta" (reabrir). |
motivoIdstring|intopcional | Motivo de pérdida (de listarMotivosPerdida). Solo se aplica con resultado: "perdido". |
comentariosstringopcional | Comentario libre sobre la pérdida. |
valor_cierrenumberopcional | Importe de cierre de la oportunidad. Se actualiza en cualquiera de los tres resultados. |
fecha_cierredateopcional | Fecha del cierre (YYYY-MM-DD). Por defecto, ahora. Ignorada al reabrir. |
Ejemplo de petición
curl -X PUT 'https://api.afer.pro/api/v1/crm/opportunities/aBc123XyZ…/close' \
-H 'X-API-KEY: afer_tk_TU_TOKEN' \
-H 'X-API-SECRET: afer_sk_TU_SECRET' \
-H 'Content-Type: application/json' \
-d '{
"resultado": "perdido",
"motivoId": "dEf456…",
"comentarios": "Se fue con la competencia por precio"
}'
<?php
$data = [
'resultado' => 'perdido',
'motivoId' => 'dEf456…',
'comentarios' => 'Se fue con la competencia por precio',
];
$ch = curl_init('https://api.afer.pro/api/v1/crm/opportunities/aBc123XyZ…/close');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-KEY: afer_tk_TU_TOKEN',
'X-API-SECRET: afer_sk_TU_SECRET',
'Content-Type: application/json',
]);
$respuesta = json_decode(curl_exec($ch), true);
curl_close($ch);
const respuesta = await fetch('https://api.afer.pro/api/v1/crm/opportunities/aBc123XyZ…/close', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'afer_tk_TU_TOKEN',
'X-API-SECRET': 'afer_sk_TU_SECRET'
},
body: JSON.stringify({
"resultado": "perdido",
"motivoId": "dEf456…",
"comentarios": "Se fue con la competencia por precio"
})
});
const resultado = await respuesta.json();
Respuesta
{
"errorCode": 200,
"errorMsg": "",
"data": {
"oportunidadId": "aBc123XyZ…",
"titulo": "Reforma local C/ Mayor",
"resultado": "perdido",
"fecha_cierre": "2026-08-19 10:24:00",
"motivo": "Precio"
}
}
Errores
| Caso | Resultado |
|---|---|
| Sin credenciales de API key | errorCode 401. |
resultado distinto de ganado/perdido/abierta, o oportunidadId ausente |
errorCode 400. |
motivoId que no existe en tu cuenta |
errorCode 400. |
| La oportunidad no existe o no es de tu cuenta | errorCode 404. |
- La fecha de cierre es la que usan las métricas de ganadas/perdidas por período en consultarOportunidades y consultarCRM.
- Acepta la cabecera
X-IDEMPOTENCY-KEYcontra dobles clicks.