# Creating a document

Creating documents differs slightly from other mutations because it involves uploading a file. First, we need to write the *mutation*:

<pre class="language-graphql"><code class="lang-graphql">mutation CreateDocumentMutation(
  $document: DocumentInput!, # Definition of the $document variable
  $signers: [SignerInput!]!, # $signers and $file, with its respective
  $file: Upload!             # types. (The "!" indicate that are
<strong>) {                          # mandatory parameters)      
</strong>  createDocument(
    document: $document,     # Pass the variable values to the mutation parameters
    signers: $signers,       # 
    file: $file,             #
    organization_id: 123,    # OPTIONAL: Creates in other user organizations, otherwise uses the current one
    folder_id: "a1b2c3"      # OPtIONAL: Creates archived in a folder
  ) {
    id
    name
    refusable
    sortable
    created_at
    signatures {
      public_id
      name
      email
      created_at
      action { name }
      link { short_link }
      user { id name email }
    }
  }
}
</code></pre>

{% hint style="info" %}
Maximum file size is 5MB on the free plan and 20MB on the professional plan!
{% endhint %}

Next, we need the values of the variables defined in the mutation in a JSON:

{% code overflow="wrap" %}

```json
/*
 Below, a signer will receive the signature link by email when the "email" field is provided, for a signer added with "name", the "link" attribute will be returned in the document with the signature link.
When using "phone", there are two possible delivery methods defined by the "delivery_method" attribute:
"DELIVERY_METHOD_WHATSAPP" to send via WhatsApp and "DELIVERY_METHOD_SMS" to send via SMS.
*/

{
  "document": {
    "name": "Marketing contract"
  },
  "signers": [{
    "email": "change-this-public-email@example.com",
    "action": "SIGN"
  }, {
    "name": "Ronaldo Fuzinato",
    "action": "SIGN"
  }, {
    "phone": "+5554999999999",
    "delivery_method": "DELIVERY_METHOD_WHATSAPP",
    "action": "SIGN"
  }, {
    "phone": "+5554999999998",
    "delivery_method": "DELIVERY_METHOD_SMS",
    "action": "SIGN"
  }]
}
```

{% endcode %}

Notice that no value has been provided for the `$file` variable? That's because since the file is being uploaded, the request needs to be sent as `multipart/form-data`, so the file must be handled a bit differently. You can do this directly in  [Altair](https://altair.autentique.com.br/):

<figure><img src="/files/iVY02GSWe0S9zk0nBKq8" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
If you're unsure how document submission works for your integration, this repository provides more information and examples on how to handle the upload: <https://github.com/jaydenseric/graphql-multipart-request-spec>.
{% endhint %}

### Creating documents on Sandbox

Our API also supports sending test documents, which do not consume document credits, making integration easier for those who have not yet acquired a plan with unlimited documents. To learn how to do this, visit our [sandbox page](/api/integration-basics/sandbox-testes.md).

### More options:

```json
// IMPORTANT:
// - If you copy this JSON, remove the comments before using it
// - Some of the attributes below will not work without a corporate plan
// - Some of the attributes below will consume additional verification credits

{
  "document": {
    "name": "Marketing contract",
    "message": "Custom message sent to the signer's email",
    "reminder": "WEEKLY", // Weekly signature reminder. DAILY to daily reminder
    "whatsapp_template": "STANDARD", //Selects WhatsApp template. Also accepts the values FORMAL, CASUAL and DIRECT 
    "sortable": true, // Signers sign on the array order "signers"
    "footer": "BOTTOM", // Adds footer. Also accepts the values LEFT and RIGHT
    "refusable": true, // Allows document rejection
    "qualified": true, // Enables qualified signature using certificates
    "scrolling_required": true, // Only allows document signing if the signer has scrolled through the entire page
    "stop_on_rejected": true, // Prevents others from signing when rejected
    "new_signature_style": true, // Enables new signature fields
    "show_audit_page": false, // Prevents creating the last audit page in documents with "new_signature_style": true
    "ignore_cpf": true, // Removes the requirement to fill in CPF to sign and removes any reference to CPF in the platform interface
    "ignore_birthdate": true // Removes the requirement to fill in the date of birth and removes any reference to the date of birth in the platform interface
    "email_template_id": 1234, // Uses a specific email template by its ID
    "deadline_at": "2023-11-24T02:59:59.999Z", // Blocks signatures after date
    "cc": [
      // Sends emails when the document is signed by all signers
      { "email": "email-cc-1@example.com" },
      { "email": "email-cc-2@example.com" }
    ],
    "expiration": {
      // Sends a reminder "days_before" days before the document’s due date specified in "notify_at"
      "days_before": 7,
      "notify_at": "20/01/2026"
    },
    "configs": {
      "notification_finished": true, // Sends an email notifying all signers that the document has been signed by all parties
      "notification_signed": true, // Sends an email to the signer notifying that they signed the document
      "signature_appearance": "ELETRONIC", // Forces the signature appearance, can be: DRAW, HANDWRITING, ELECTRONIC, IMAGE
      "keep_metadata": true, // Keeps PDF metadata in qualified signature
      "lock_user_data": true // Keeps outdated user data, showing the information used at the time of signing
    },
    "locale": {
      "country": "BR", // Any country in ISO3166 format, if not provided, defaults to BR
// IMPORTANT The creation of non-Brazilian documents has the following points:
// - Signers with SMS delivery method are not supported. In these cases,
// the request returns the error: sms_delivery_not_allowed_on_foreign_documents;
// - The fields new_signature_style and ignore_cpf are set to true;
// - CPF elements placed on the document pages are ignored;
// - Additional verifications from SERPRO and via SMS are ignored.
      "language": "pt-BR", // Can be: pt-BR or en-US, if not provided, defaults to pt-BR
      "timezone": "America/Sao_Paulo", // DateTimeZone with all time zones, if not provided, defaults to America/Sao_Paulo
// A complete list can be found at: https://www.php.net/manual/en/datetimezone.listidentifiers.php
      "date_format": "DD_MM_YYYY", // Enum, can be: DD_MM_YYYY or MM_DD_YYYY, if not provided, defaults to DD_MM_YYYY
    } 
  },
  "signers": [{
    "email": "change-this-public-email@example.com", // Envia email
    "action": "SIGN", // Sign
    "configs": { "cpf": "12345678900" }, // Validates the cpf of the signer
    "security_verifications": [
      // Require SMS verification ("verify_phone" is optional):
      { "type": "SMS", "verify_phone": "+5554999999999" },
      // Require photo ID (Manual approval)
      { "type": "MANUAL" }
    ],
    //Positions signature fields:
    "positions": [{"x": "5.0", "y": "90.0", "z": 1, "element": "SIGNATURE"}]
  }, {
    "name": "Ronaldo Fuzinato", // Receives signature links to send
    "action": "SIGN_AS_A_WITNESS", // Sign as a witness
    // Require photo ID (Photo ID)
    "security_verifications": [{ "type": "UPLOAD" }],
    // Position fields for name of the signer
    "positions": [{"x": "75.0", "y": "90.0", "z": 1, "element": "NAME"}]
  }, {
    "email": "change-this-public-email-2@example.com", // Send email
    "action": "APPROVE", // Approve
    // Require photo ID (Document, selfie, and liveness check)
    "security_verifications": [{ "type": "LIVE" }],
    // Positions initials fields
    "positions": [{"x": "25.0", "y": "90.0", "z": 1, "element": "INITIALS"}]
  }, {
    "phone": "+5521999999999",
    "delivery_method": "DELIVERY_METHOD_SMS", // Send SMS to "phone"
    "action": "RECOGNIZE", // Acknowledge
    // Demand Photo ID (SERPRO biometrics):
    "security_verifications": [{ "type": "PF_FACIAL" }],
    // Position fields of signature date:
    "positions": [{"x": "55.0", "y": "90.0", "z": 1, "element": "DATE"}]
  }, {
    "phone": "+5521999999998",
    "delivery_method": "DELIVERY_METHOD_WHATSAPP", // Sends whatsapp to "phone"
    "action": "SIGN", // Sign
    // Position CPF fields:
    "positions": [{"x": "55.0", "y": "90.0", "z": 1, "element": "CPF"}]
  }]
}
```

### &#x20;Additional Validations

You can implement additional validations in your documents. These configurations must be included in the `security_verifications` list of the signer object, using the `type` field to define the desired challenge modality. In addition to the types, fields such as `verify_phone` and `cpf` assist in the delivery of security codes and in the precise identification of the signer.

| Field / Verification Type       | How it works                                                                                                                                                                                                             |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `verify_phone`                  | The signer must validate a mobile number through a code sent via SMS. You can pre-fill the number or leave it blank so the signer can provide it themselves.                                                             |
| `cpf`                           | Configuration that ensures only the signer with the specified CPF can sign the document. If defined, the system forces the entry or validation of this data in the signer's account                                      |
| `MANUAL`                        | The signer will attach a photo ID and take a selfie. You or a member of your organization can then approve or reject the submitted documents and selfie                                                                  |
| `UPLOAD`                        | The signer must attach the front and back of a photo ID using their smartphone or computer                                                                                                                               |
| `LIVE`                          | The signer will need to attach a photo ID, take a selfie with their smartphone, and perform a liveness check (video). The document photo will be automatically compared to the selfie to verify the degree of similarity |
| `PF_FACIAL`                     | The signer takes a selfie which is validated by SERPRO, comparing it to Brazilian government registration photos linked to the informed CPF                                                                              |
| `BIOMETRIC_AND_TEXT_EXTRACTION` | The signer will need to photograph an ID document and take a selfie, the document photo will be compared with the selfie to determine the similarity score.                                                              |
| `LIVENESS_AND_TEXT_EXTRACTION`  | The signer will need to perform a liveness check and photograph a photo ID. Document information will be automatically extracted and compared to verify the similarity score.                                            |

<details>

<summary><strong>Positioning signature fields "positions"</strong></summary>

As shown in the example above, to add signature fields when creating the document, you need to include the "positions" attribute.

```json
{
  ...
  "signers": [
    {
      ...
      "positions": [
        { "x": "100.0", "y": "100.0", "z": 1, "element": "SIGNATURE" }
      ]﻿
    }
  ]﻿
}
```

The “x” value represents the horizontal position, ranging from 0% to 100%.\
The “y” value represents the vertical position, also ranging from 0% to 100%.\
The “z” value indicates the page number, starting at 1.

\
﻿O `"element"` It's the type of signature\
﻿`"SIGNATURE"`: Signature\
`"NAME"`: Signer's name\
`"INITIALS"`: Initials\
`"DATE"`: Signature date\
`"CPF"`: Signer CPF

To know what positions to pass for x and y, you can create a sample document in the Autentique dashboard and retrieve the positions by fetching the document using "positions":

```graphql
query {
  document(id: "DOCUMENT_ID") {
    id
    signatures {
      public_id
      positions {
        element
        x
        y
        z
      }
    }
  }
}
```

</details>

<details>

<summary><strong>Require SMS verification and/or photo document verification "security_verifications"</strong></summary>

To require signers to verify via SMS and/or photo document, you need to add the "security\_verifications" attribute to the signer for whom these verifications should be required. Remember to check in the dashboard for the cost of additional verification credits needed.

```json
{
  ...
  "signers": [
    {
      ...
      "security_verifications": [
        { "type": "SMS", "verify_phone": "+5554999999999" },
        { "type": "MANUAL" }
      ]﻿
    },
    {
      ...
      "security_verifications": [
        { "type": "BIOMETRIC_AND_TEXT_EXTRACTION" }
      ]﻿
    },
    {
      ...
      "security_verifications": [
        { "type": "BIOMETRIC_AND_TEXT_EXTRACTION", "fallback_behavior": "DISABLE_FALLBACK" }
      ]﻿
    }
  ]﻿
}

```

The "type" is the type of verification:

* **"`SMS`"**: SMS validation ("verify\_phone" is optional and requires a specified phone number)
* **"`MANUAL`"**: Require a photo document (manual approval)
* **"`UPLOAD`"**: Require a photo document (photo document)
* **"`LIVE`"**: Require a photo document (document, selfie, and proof of life)
* **"`PF_FACIAL`"**: Require a photo document (SERPRO biometric verification)
* "**`BIOMETRIC_AND_TEXT_EXTRACTION`**": Require a photo document (photo document and facematch)

While it's possible to have multiple verifications for the same signer, you can only choose one of the following options per signer: **`MANUAL`**, **`UPLOAD`**, **`LIVE`**, and **`PF_FACIAL`**.

\
When the types **`UPLOAD`**, **`LIVE`**, **`PF_FACIAL`** and **`BIOMETRIC_AND_TEXT_EXTRACTION`** are used, there is a default behavior where they are changed to `MANUAL` when the signer exceeds the maximum number of attempts in the document validation process. \
To disable this behavior, you must use the `fallback_behavior` parameter, which will flag the document as failed and automatically reject it.

</details>

<details>

<summary><strong>Create a document from a template</strong></summary>

There is no way in the API to directly use the panel templates to create documents. However, you can achieve something similar through your code:

1. **Create a fixed HTML template** on your machine, marking the places with variables to be replaced by values. (e.g., "I, $NomeSignatario$, accept this contract")
2. **Programmatically duplicate this HTML** and in the duplicate, replace the variable fields with the actual values. (e.g., `$NomeSignatario$` → Jorge Silva)
3. **Send this HTML file** with the replaced values to our API through the `createDocument` mutation, just like it works for other types of files.

</details>

<details>

<summary><strong>Example of document creation with NodeJS</strong></summary>

If you use Postman, you can generate these examples from the Postman collection provided here in the [documentation](https://docs.autentique.com.br/api/).

```javascript
var axios = require('axios');
var FormData = require('form-data');
var fs = require('fs');
var data = new FormData();
data.append('operations', '{"query":"mutation CreateDocumentMutation($document: DocumentInput!, $signers: [SignerInput!]!, $file: Upload!) {createDocument(document: $document, signers: $signers, file: $file) {id name refusable sortable created_at signatures { public_id name email created_at action { name } link { short_link } user { id name email }}}}", "variables":{"document": {"name": "Test contract"},"signers": [{"email": "change-this-public-email@example.com","action": "SIGN"}],"file":null}}');
data.append('map', '{"file": ["variables.file"]}');
data.append('file', fs.createReadStream('/path/to/file'));
var config = {
  method: 'post',
  url: 'https://api.autentique.com.br/v2/graphql',
  headers: {
    'Authorization': 'Bearer API_TOKEN',
    ...data.getHeaders()
  },
  data : data
};
axios(config)
  .then(function(response) { console.log(JSON.stringify(response.data)); })
  .catch(function(error) { console.log(error); });
```

For this example, just replace the API token, the signer's email, and the file path.

</details>

<details>

<summary><strong>Example of document creation with PHP</strong></summary>

If you use Postman, you can generate these examples from the Postman collection provided here in the documentation [documentation](https://docs.autentique.com.br/api/).

```php
<?php

$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://api.autentique.com.br/v2/graphql',
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS => array('operations' => '{"query":"mutation CreateDocumentMutation($document: DocumentInput!, $signers: [SignerInput!]!, $file: Upload!) {createDocument(document: $document, signers: $signers, file: $file) {id name refusable sortable created_at signatures { public_id name email created_at action { name } link { short_link } user { id name email }}}}", "variables":{"document": {"name": "Contrato de teste"},"signers": [{"email": "change-this-public-email@example.com","action": "SIGN"}],"file":null}}','map' => '{"file": ["variables.file"]}','file'=> new CURLFILE('/path/to/file')),
  CURLOPT_HTTPHEADER => array('Authorization: Bearer API_TOKEN'),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```

In this example, you just need to replace the API token, the signer's email, and the file path.

</details>

<details>

<summary><strong>Example of document creation with Python3</strong></summary>

If you use Postman, you can generate these examples from the Postman collection provided here in the documentation [documentation](https://docs.autentique.com.br/api/).

```python
import requests

url = "https://api.autentique.com.br/v2/graphql"
payload = {
  'operations': '{"query":"mutation CreateDocumentMutation($document: DocumentInput!, $signers: [SignerInput!]!, $file: Upload!) {createDocument(document: $document, signers: $signers, file: $file) {id name refusable sortable created_at signatures { public_id name email created_at action { name } link { short_link } user { id name email }}}}", "variables":{"document": {"name": "Test contract"},"signers": [{"email": "change-this-public-email@example.com","action": "SIGN"}],"file":null}}',
  'map': '{"file": ["variables.file"]}'
}
files = [
  ('file',open('/path/to/file.pdf','rb'))
]
headers = {
  'Authorization': 'Bearer API_TOKEN'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
```

In this example, you just need to replace the API token, the signer's email, and the file path.

</details>

<details>

<summary><strong>Example of document creation with C#</strong></summary>

If you use Postman, you can generate these examples from the Postman collection provided here in the documentation [documentation](https://docs.autentique.com.br/api/).

```csharp
var client = new RestClient("https://api.autentique.com.br/v2/graphql");
var request = new RestRequest(Method.POST);

request.AddHeader("Authorization", "Bearer API_TOKEN");
request.AddParameter("operations", "{\"query\":\"mutation CreateDocumentMutation($document: DocumentInput!, $signers: [SignerInput!]!, $file: Upload!) {createDocument(document: $document, signers: $signers, file: $file) {id name refusable sortable created_at signatures { public_id name email created_at action { name } link { short_link } user { id name email }}}}\", \"variables\":{\"document\": {\"name\": \"Contrato de teste\"},\"signers\": [{\"email\": \"change-this-public-email@example.com\",\"action\": \"SIGN\"}],\"file\":null}}");
request.AddParameter("map", "{\"file\": [\"variables.file\"]}");
request.AddFile("file", "/path/to/file");
IRestResponse response = client.Execute(request);

Console.WriteLine(response.Content);
```

In this example, you just need to replace the API token, the signer's email, and the file path.

</details>

{% hint style="info" %}
You can check what each of these parameters means directly in the full GraphQL API documentation, in the Docs menu of [Altair](https://altair.autentique.com.br/). If you're not sure how to do that, check out our tutorial on [**Using Altair**](/api/integration-basics/altair.md).
{% endhint %}

{% file src="/files/-M03o9cE5QB3vLoPUlzJ" %}
Para importar e usar no Postman
{% endfile %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.autentique.com.br/api/mutations/criando-um-documento.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
