Fuente: https://crm.begraffic.com/docs/api
Índice para agentes: [llms.txt](https://crm.begraffic.com/llms.txt)

# PUT /api/v1/emails/templates/{key}

URL base: https://crm.begraffic.com. Autenticación: Authorization: Bearer <CLAVE_V1_bcrm_...>.

Definición OpenAPI de la operación (los bloques schema son esquemas, no cuerpos de ejemplo):

```json
{
  "operationId": "emails.templates.upsert",
  "summary": "Crear o actualizar una plantilla de la aplicación",
  "description": "Crea (201) o actualiza (200) la plantilla `key` de la aplicación en el workspace: el dueño es la aplicación OAuth (su cliente) o, con una clave v1, la clave. Repetir la llamada actualiza la MISMA plantilla. Queda publicada y visible en el panel; Be CRM añade el pie obligatorio (empresa y «Darse de baja»). Se envía con `POST /api/v1/emails` y `template.name` = `name` de la respuesta (`sesTemplateId`). No consume cuota. 400 si `key` o alguna `{{variable}}` no son válidas; 409 si ese id pertenece a otra aplicación; 503 si el proveedor de correo falla (no queda ninguna plantilla publicada a medias).",
  "tags": [
    "Correo"
  ],
  "x-scope": "templates:write",
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "parameters": [
    {
      "name": "key",
      "in": "path",
      "required": true,
      "description": "Clave de la plantilla para la aplicación: `^[a-z0-9][a-z0-9._-]{0,63}$` (p. ej. `bechurch.felicitacion`). Una clave inválida responde 400.",
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": false,
      "description": "Clave única por operación (≤ 255 caracteres). Repetir la misma petición devuelve la misma respuesta durante 24 h; con otro cuerpo, 422.",
      "schema": {
        "type": "string",
        "maxLength": 255
      }
    }
  ],
  "responses": {
    "200": {
      "description": "Correcto.",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string"
                  },
                  "templateId": {
                    "type": "string",
                    "description": "Id de la plantilla en el workspace."
                  },
                  "name": {
                    "type": "string",
                    "description": "`sesTemplateId`: el `template.name` de `POST /api/v1/emails` para enviarla."
                  },
                  "status": {
                    "type": "string",
                    "const": "published"
                  },
                  "variables": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Variables de la plantilla (sin las del sistema: companyName, unsubscribeUrl…)."
                  },
                  "updatedAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "key",
                  "templateId",
                  "name",
                  "status",
                  "variables",
                  "updatedAt"
                ]
              }
            }
          }
        }
      }
    },
    "201": {
      "description": "Creado.",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string"
                  },
                  "templateId": {
                    "type": "string",
                    "description": "Id de la plantilla en el workspace."
                  },
                  "name": {
                    "type": "string",
                    "description": "`sesTemplateId`: el `template.name` de `POST /api/v1/emails` para enviarla."
                  },
                  "status": {
                    "type": "string",
                    "const": "published"
                  },
                  "variables": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Variables de la plantilla (sin las del sistema: companyName, unsubscribeUrl…)."
                  },
                  "updatedAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "key",
                  "templateId",
                  "name",
                  "status",
                  "variables",
                  "updatedAt"
                ]
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "`invalid_request`: Petición inválida (cuerpo, parámetros o consulta).",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "`unauthorized`: Falta la clave, no existe, está revocada o caducó.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "`insufficient_scope`: La clave no tiene el alcance que exige la ruta.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "`conflict`: Conflicto con el estado actual (p. ej. ya existe). `idempotency_in_progress`: Otra petición con la misma Idempotency-Key se está procesando.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "422": {
      "description": "`idempotency_key_reused`: La Idempotency-Key ya se usó con otra petición.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "`rate_limited`: Demasiadas llamadas (límite por clave y minuto). Ver `Retry-After`.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "500": {
      "description": "`internal`: Error interno.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "`unavailable`: Servicio no disponible temporalmente.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "minLength": 1,
              "maxLength": 120,
              "description": "Nombre visible en el panel de plantillas."
            },
            "subject": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "description": "Asunto; admite `{{variables}}`."
            },
            "html": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200000,
              "description": "HTML completo. El pie obligatorio (empresa y «Darse de baja») lo añade Be CRM."
            },
            "text": {
              "description": "Versión de texto plano. Sin ella se deriva del HTML.",
              "type": "string",
              "maxLength": 50000
            },
            "description": {
              "type": "string",
              "maxLength": 500
            },
            "previewText": {
              "type": "string",
              "maxLength": 200
            }
          },
          "required": [
            "name",
            "subject",
            "html"
          ],
          "additionalProperties": false
        }
      }
    }
  }
}
```
