> ## Documentation Index
> Fetch the complete documentation index at: https://www.octoparse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Assembla una cartella contratto

> Unisci JSON contratto multi-file in un manifest pienamente validato. Accesso anonimo consentito.

**`POST`** `https://api-datahub.octoparse.com/v1/data-apps/contract/assemble`

Autenticazione: nessuna. Accesso anonimo consentito.

Unisce una cartella del contratto (una mappa di file indicizzata per percorso relativo, con l'ordine preservato) in un unico manifest autonomo. Questo endpoint è l'unica fonte di riferimento per le regole di assemblaggio. La procedura guidata di importazione del portale e l'autocontrollo dello skill del contratto lo usano entrambi.

File slot: `dataapp.json`/⟦1/`output_schema.json`/`runtime.json`/`pricing.json`/`examples.json` ⟧/`README.md` (i nomi dei file non fanno distinzione tra maiuscole e minuscole; le forme punteggiate come `input.schema.json` sono accettate e normalizzate in `picked`). Prezzi ed esempi possono anche essere inseriti in `dataapp.json`. Il manifesto unito passa attraverso la convalida completa lato autore (stesse regole di Convalida un manifesto). Consegnabile solo quando `issues` è vuoto. Le anomalie recuperabili (file mancanti, collisioni di nomi tra livelli, file non contrattuali ignorati, mancata corrispondenza dei nomi delle cartelle e così via) restituiscono come strutturato `warnings` (`code` + `params`, localizzato dal livello di presentazione) e non sono errori.

Hard failure (`400`): un file slot non è JSON valido, ha forma sbagliata (`examples.json` deve essere array; gli altri slot sono oggetti) o supera 1MB; nessun file contratto; size totale oltre 12MB. Il path contratto copre solo api-kind; `runtime.kind=code` produce un issue.

L’8° file opzionale `i18n.json` (`{source, locales}`, fino a 4MB) **non** viene unito nel manifest. È parsato e restituito come `translations` perché il caller lo salvi tramite gli endpoint di traduzione. `source` dovrebbe allinearsi a `source_locale` dell’app.

Accesso anonimo consentito: l’assembly è funzione pura del body, non legge né scrive dati piattaforma; unici gate i limiti di size file/totale.

## Richiesta

### Body della richiesta

<ParamField body="files" type="object" required>
  Mappa dei file. Le chiavi sono percorsi relativi; i valori sono il testo dei file.
</ParamField>

### Esempio di richiesta

```bash theme={null}
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"files": {"dataapp.json": "{\"spec_version\": \"0.2\", \"identity\": {…}}", "input_schema.json": "{\"type\": \"object\", …}", "output_schema.json": "{\"id_field\": \"review_id\", …}", "runtime.json": "{\"kind\": \"api\", …}", "pricing.json": "{\"events\": [...]}", "examples.json": "[...]", "README.md": "# Product review lookup"}}' \
  "https://api-datahub.octoparse.com/v1/data-apps/contract/assemble"
```

## Risposta

### 200 successo

```json theme={null}
{
  "data": {
    "manifest": {
      "spec_version": "0.2",
      "identity": {
        "app_name": "reviews-query",
        "name": "Product review lookup"
      },
      "…": "…"
    },
    "picked": {
      "dataapp.json": "dataapp.json",
      "input_schema.json": "input_schema.json"
    },
    "issues": [],
    "warnings": [
      {
        "code": "contract-folder-name-mismatch",
        "params": {
          "expected": "reviews-query",
          "actual": "reviews"
        }
      }
    ],
    "card": {
      "app_name": "reviews-query",
      "name": "Product review lookup"
    },
    "translations": null
  }
}
```

Il payload è wrappato in `data`. Campi:

<ResponseField name="manifest" type="object" required>
  Oggetto manifest unito.
</ResponseField>

<ResponseField name="picked" type="string[]">
  Mappa dei file slot effettivamente riconosciuti.
</ResponseField>

<ResponseField name="folder_name" type="string">
  —
</ResponseField>

<ResponseField name="issues" type="object[]">
  Problemi di validazione. Vuoto significa pronto per la consegna.

  <Expandable title="fields">
    <ResponseField name="path" type="string" required>
      —
    </ResponseField>

    <ResponseField name="message" type="string" required>
      —
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="warnings" type="object[]">
  Avvisi strutturati.

  <Expandable title="fields">
    <ResponseField name="code" type="string" required>
      —
    </ResponseField>

    <ResponseField name="params" type="object">
      —
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="translations" type="object">
  Contenuto analizzato di `i18n.json`, oppure `null` se assente.

  <Expandable title="fields">
    <ResponseField name="source" type="string" required>
      —
    </ResponseField>

    <ResponseField name="locales" type="object">
      —
    </ResponseField>
  </Expandable>
</ResponseField>

### Errori

| HTTP | `code`                  | `category`      | Descrizione                                                                                                          |
| ---- | ----------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------- |
| 400  | `contract-file-invalid` | `invalid_input` | Un file del contratto non è JSON valido, ha una struttura errata o supera 1MB; oppure in `i18n.json` manca `source`. |
| 400  | `contract-empty`        | `invalid_input` | Il set di file non contiene file slot di contratto.                                                                  |
| 400  | `locale-invalid`        | `invalid_input` | Il codice locale non è valido.                                                                                       |
| 413  | `payload-too-large`     | `invalid_input` | Il body supera il limite di size.                                                                                    |

Le risposte di errore usano `{"error": {code, category, message, retryable}}`. Vedi <a href="/docs/it/datahub/api/reference/introduction#errors">Errori</a>.

## Librerie client

Gli SDK Python e JavaScript non wrappano ancora questo endpoint. Chiama REST direttamente.
