> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ovac.councilbox.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ovac.councilbox.com/_mcp/server.

# Upload Appointment Act

POST https://api.ovac.pre.councilbox.com/council/{councilId}/act
Content-Type: multipart/form-data

# Upload Appointment Act (`POST` - REST)

A diferencia del resto de la API, este método no utiliza la arquitectura GraphQL. Se trata de un endpoint REST nativo diseñado específicamente para la transferencia de archivos binarios, permitiendo la carga del acta final previamente modificado con información propia de la organización.

Esta modalidad permite al cliente incorporar elementos adicionales, como un código de verificación, un sello corporativo o cualquier otra marca identificativa, aportando al documento final un mayor grado de personalización y alineación con la imagen corporativa de la entidad.

### Detalles de la Solicitud

- **Método HTTP:** `POST`
    
- **URL:** `https://api.ovac.pre.councilbox.com/council/:councilId/act`
    
- **Content-Type:** `multipart/form-data`
    

### Cabeceras (Headers)

| **Key** | **Value** | **Requerido** | **Descripción** |
| --- | --- | --- | --- |
| **x-jwt-token** | {{token}} | SI | Token JWT de autenticación obtenido previamente en el método de login. |

## Referencia de la API

### Parámetros de Ruta (Path Parameters)

| Parámetro | Descripción | Requerido | Tipo |
| --- | --- | --- | --- |
| councilId | Identificador único de la cita a la que se desea permitir el acceso. | SI | Integer |

### Cuerpo de la Petición (Body Parameters - `form-data`)

| Parámetro | Descripción | Requerido | Tipo |
| --- | --- | --- | --- |
| file | Archivo físico del informe o acta (normalmente PDF) que contiene el CEA para almacenar en OVAC. | SI | File (Binary) |
| notify | Control de notificaciones automáticas:  <br>`true` -> Envía siempre una notificación al ciudadano informándole de la disponibilidad del documento (Valor por defecto si se omite).  <br>Cualquier otro valor -> El sistema procesará el archivo sin enviar notificación al ciudadano. | NO | Boolean |

> ⚙️ **Prerrequisitos de negocio:**  
Para que el backend acepte la carga del archivo, la cita debe encontrarse estrictamente en estado **`45`** (Procesando informe). Adicionalmente, este flujo requiere que la opción _"Mostrar footer en informe de cita"_ esté deshabilitada. 
  

## Ejemplos de código y peticiones

### 1\. Ejemplo de comando -cURL

Al tratarse de una petición de tipo formulario multimedia (`multipart/form-data`), la estructura define los campos del cuerpo de forma independiente al archivo binario:

``` bash
curl --location "https://api.ovac.pre.councilbox.com/council/64879/act" \
--header "x-jwt-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzZTVhZTA1NC1jZGUyLTQ0MWEtYTY3Zi1kMGExNzYwYzUxNzYiLCJ1c2VyX2lkIjozNDc2LCJ0b2tlbl90eXBlIjoidXNlciIsImlhdCI6MTc3OTE3NjE2M30.0cWaj4uUaArUQR3C-RwqlpLafkX5Rih4LZs9ZPNpEFY" \
--form "file=@\"/Ruta/Documentos/Informes/64879.pdf\"" \
--form "notify=\"true\""

 ```

## Resultados Esperados (Respuestas HTTP)

### Caso A: Éxito (200 OK)

Si la cita se encuentra en el estado correcto (`45`) y el archivo se procesa sin anomalías.

``` json
{
    "success": true
}

 ```

### Caso B: Error de Validación (400 / 403 Bad Request)

Si la cita ya ha sido cerrada, no está en estado `45`, o la configuración de la organización deniega la inserción manual del documento externo.

``` json
{
    "message": "This council is not expecting this action"
}

 ```

> 💡 **Tip para la integración en Postman:** > Al dar de alta esta petición en tu colección, ve a la pestaña **Body**, marca la opción **form-data** y, al escribir la clave `file`, pasa el ratón sobre el extremo derecho de la casilla de texto para cambiar el desplegable de **Text** a **File**. Esto habilitará el botón nativo para seleccionar y adjuntar tu PDF de prueba.

Reference: https://docs.ovac.councilbox.com/metodos-api/03-manage-appointments/upload-appointment-act

## OpenAPI Specification

```yaml
openapi: 3.1.0
info:
  title: ovac
  version: 1.0.0
paths:
  /council/{councilId}/act:
    post:
      operationId: upload-appointment-act
      summary: Upload Appointment Act
      description: >-
        # Upload Appointment Act (`POST` - REST)


        A diferencia del resto de la API, este método no utiliza la arquitectura
        GraphQL. Se trata de un endpoint REST nativo diseñado específicamente
        para la transferencia de archivos binarios, permitiendo la carga del
        acta final previamente modificado con información propia de la
        organización.


        Esta modalidad permite al cliente incorporar elementos adicionales, como
        un código de verificación, un sello corporativo o cualquier otra marca
        identificativa, aportando al documento final un mayor grado de
        personalización y alineación con la imagen corporativa de la entidad.


        ### Detalles de la Solicitud


        - **Método HTTP:** `POST`
            
        - **URL:** `https://api.ovac.pre.councilbox.com/council/:councilId/act`
            
        - **Content-Type:** `multipart/form-data`
            

        ### Cabeceras (Headers)


        | **Key** | **Value** | **Requerido** | **Descripción** |

        | --- | --- | --- | --- |

        | **x-jwt-token** | {{token}} | SI | Token JWT de autenticación obtenido
        previamente en el método de login. |


        ## Referencia de la API


        ### Parámetros de Ruta (Path Parameters)


        | Parámetro | Descripción | Requerido | Tipo |

        | --- | --- | --- | --- |

        | councilId | Identificador único de la cita a la que se desea permitir
        el acceso. | SI | Integer |


        ### Cuerpo de la Petición (Body Parameters - `form-data`)


        | Parámetro | Descripción | Requerido | Tipo |

        | --- | --- | --- | --- |

        | file | Archivo físico del informe o acta (normalmente PDF) que
        contiene el CEA para almacenar en OVAC. | SI | File (Binary) |

        | notify | Control de notificaciones automáticas:  <br>`true` -> Envía
        siempre una notificación al ciudadano informándole de la disponibilidad
        del documento (Valor por defecto si se omite).  <br>Cualquier otro valor
        -> El sistema procesará el archivo sin enviar notificación al ciudadano.
        | NO | Boolean |


        > ⚙️ **Prerrequisitos de negocio:**  

        Para que el backend acepte la carga del archivo, la cita debe
        encontrarse estrictamente en estado **`45`** (Procesando informe).
        Adicionalmente, este flujo requiere que la opción _"Mostrar footer en
        informe de cita"_ esté deshabilitada. 
          

        ## Ejemplos de código y peticiones


        ### 1\. Ejemplo de comando -cURL


        Al tratarse de una petición de tipo formulario multimedia
        (`multipart/form-data`), la estructura define los campos del cuerpo de
        forma independiente al archivo binario:


        ``` bash

        curl --location "https://api.ovac.pre.councilbox.com/council/64879/act"
        \

        --header "x-jwt-token:
        eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzZTVhZTA1NC1jZGUyLTQ0MWEtYTY3Zi1kMGExNzYwYzUxNzYiLCJ1c2VyX2lkIjozNDc2LCJ0b2tlbl90eXBlIjoidXNlciIsImlhdCI6MTc3OTE3NjE2M30.0cWaj4uUaArUQR3C-RwqlpLafkX5Rih4LZs9ZPNpEFY"
        \

        --form "file=@\"/Ruta/Documentos/Informes/64879.pdf\"" \

        --form "notify=\"true\""

         ```

        ## Resultados Esperados (Respuestas HTTP)


        ### Caso A: Éxito (200 OK)


        Si la cita se encuentra en el estado correcto (`45`) y el archivo se
        procesa sin anomalías.


        ``` json

        {
            "success": true
        }

         ```

        ### Caso B: Error de Validación (400 / 403 Bad Request)


        Si la cita ya ha sido cerrada, no está en estado `45`, o la
        configuración de la organización deniega la inserción manual del
        documento externo.


        ``` json

        {
            "message": "This council is not expecting this action"
        }

         ```

        > 💡 **Tip para la integración en Postman:** > Al dar de alta esta
        petición en tu colección, ve a la pestaña **Body**, marca la opción
        **form-data** y, al escribir la clave `file`, pasa el ratón sobre el
        extremo derecho de la casilla de texto para cambiar el desplegable de
        **Text** a **File**. Esto habilitará el botón nativo para seleccionar y
        adjuntar tu PDF de prueba.
      tags:
        - subpackage_03ManageAppointments
      parameters:
        - name: councilId
          in: path
          required: true
          schema:
            type: string
        - name: x-jwt-token
          in: header
          description: JWT token obtained from Login.
          required: true
          schema:
            type: string
      responses:
        '200':
          description: >-
            Successful response. GraphQL business errors may be returned inside
            the JSON `errors` field while transport status remains HTTP 200.
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/03manageAppointments_upload_Appointment_Act_Response_200
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                notify:
                  type: boolean
              required:
                - file
servers:
  - url: https://api.ovac.pre.councilbox.com
    description: Pre-production
  - url: https://api.ovac.councilbox.com
    description: Production
components:
  schemas:
    03manageAppointments_upload_Appointment_Act_Response_200:
      type: object
      properties: {}
      title: 03manageAppointments_upload_Appointment_Act_Response_200
  securitySchemes:
    JwtToken:
      type: apiKey
      in: header
      name: x-jwt-token
      description: JWT token obtained from Login.

```

## Examples

### Upload Appointment Act



**Request**

```json
{}
```

**Response**

```json
{
  "success": true
}
```

**SDK Code**

```python Upload Appointment Act
import requests

url = "https://api.ovac.pre.councilbox.com/council/councilId/act"

payload = "-----011000010111000001101001--\r\n"
headers = {
    "x-jwt-token": "<apiKey>",
    "Content-Type": "multipart/form-data; boundary=---011000010111000001101001"
}

response = requests.post(url, data=payload, headers=headers)

print(response.json())
```

```javascript Upload Appointment Act
const url = 'https://api.ovac.pre.councilbox.com/council/councilId/act';
const form = new FormData();

const options = {method: 'POST', headers: {'x-jwt-token': '<apiKey>'}};

options.body = form;

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Upload Appointment Act
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.ovac.pre.councilbox.com/council/councilId/act"

	payload := strings.NewReader("-----011000010111000001101001--\r\n")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("x-jwt-token", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Upload Appointment Act
require 'uri'
require 'net/http'

url = URI("https://api.ovac.pre.councilbox.com/council/councilId/act")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["x-jwt-token"] = '<apiKey>'
request.body = "-----011000010111000001101001--\r\n"

response = http.request(request)
puts response.read_body
```

```java Upload Appointment Act
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.ovac.pre.councilbox.com/council/councilId/act")
  .header("x-jwt-token", "<apiKey>")
  .body("-----011000010111000001101001--\r\n")
  .asString();
```

```php Upload Appointment Act
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.ovac.pre.councilbox.com/council/councilId/act', [
  'headers' => [
    'Content-Type' => 'multipart/form-data; boundary=---011000010111000001101001',
    'x-jwt-token' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp Upload Appointment Act
using RestSharp;

var client = new RestClient("https://api.ovac.pre.councilbox.com/council/councilId/act");
var request = new RestRequest(Method.POST);
request.AddHeader("x-jwt-token", "<apiKey>");
request.AddHeader("Content-Type", "multipart/form-data; boundary=---011000010111000001101001");
request.AddParameter("undefined", "-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Upload Appointment Act
import Foundation

let headers = ["x-jwt-token": "<apiKey>"]
let parameters = []

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.ovac.pre.councilbox.com/council/councilId/act")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### 03manageAppointments_upload_Appointment_Act_example



**Request**

```json
{
  "file": "<file: string>",
  "notify": true
}
```

**Response**

```json
{
  "success": true
}
```

**SDK Code**

```python 03manageAppointments_upload_Appointment_Act_example
import requests

url = "https://api.ovac.pre.councilbox.com/council/councilId/act"

files = { "file": "open('string', 'rb')" }
payload = { "notify": "true" }
headers = {"x-jwt-token": "<apiKey>"}

response = requests.post(url, data=payload, files=files, headers=headers)

print(response.json())
```

```javascript 03manageAppointments_upload_Appointment_Act_example
const url = 'https://api.ovac.pre.councilbox.com/council/councilId/act';
const form = new FormData();
form.append('file', 'string');
form.append('notify', 'true');

const options = {method: 'POST', headers: {'x-jwt-token': '<apiKey>'}};

options.body = form;

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go 03manageAppointments_upload_Appointment_Act_example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.ovac.pre.councilbox.com/council/councilId/act"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"notify\"\r\n\r\ntrue\r\n-----011000010111000001101001--\r\n")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("x-jwt-token", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby 03manageAppointments_upload_Appointment_Act_example
require 'uri'
require 'net/http'

url = URI("https://api.ovac.pre.councilbox.com/council/councilId/act")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["x-jwt-token"] = '<apiKey>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"notify\"\r\n\r\ntrue\r\n-----011000010111000001101001--\r\n"

response = http.request(request)
puts response.read_body
```

```java 03manageAppointments_upload_Appointment_Act_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.ovac.pre.councilbox.com/council/councilId/act")
  .header("x-jwt-token", "<apiKey>")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"notify\"\r\n\r\ntrue\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php 03manageAppointments_upload_Appointment_Act_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.ovac.pre.councilbox.com/council/councilId/act', [
  'multipart' => [
    [
        'name' => 'file',
        'filename' => 'string',
        'contents' => null
    ],
    [
        'name' => 'notify',
        'contents' => 'true'
    ]
  ]
  'headers' => [
    'x-jwt-token' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp 03manageAppointments_upload_Appointment_Act_example
using RestSharp;

var client = new RestClient("https://api.ovac.pre.councilbox.com/council/councilId/act");
var request = new RestRequest(Method.POST);
request.AddHeader("x-jwt-token", "<apiKey>");
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"string\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"notify\"\r\n\r\ntrue\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift 03manageAppointments_upload_Appointment_Act_example
import Foundation

let headers = ["x-jwt-token": "<apiKey>"]
let parameters = [
  [
    "name": "file",
    "fileName": "string"
  ],
  [
    "name": "notify",
    "value": "true"
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.ovac.pre.councilbox.com/council/councilId/act")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```