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

# Gotchas

> Things that surprise integrators: PDF input pitfalls, why an API stakeholder is not a Contact, document-group permissions, package naming rules, and the Web Application Firewall.

This page collects the behaviours that most often trip up people building against the NSEV
WebPortal API for the first time. Each one is easy to miss and easy to design around once you
know about it.

## PDF input pitfalls

The API accepts PDFs that already carry structure - signatures, signing fields, form fields - and
it converts or repairs documents on upload. A few behaviours follow from that.

**Adding form fields to a PDF/A breaks PDF/A conformance.** PDF/A uploads are only allowed when the
source is `pdfa1a` or `pdfa2a`. If you then add form fields through the API, the "/A" conformance is
broken and you are left with a regular PDF. To recover PDF/A, set
`DocumentOptions.PdfOptions.TargetFormat` to `pdfa1a` or `pdfa2a` on the add-document call: the
breaking still happens, but once all fields have been filled or saved the document is reconverted to
the target format, producing a PDF/A document again. This conversion only takes effect when document
conversion is enabled in the tenant configuration.

<Note>
  When **itsme** is used as a signing method, `TargetFormat` of `pdfa1a` or `pdfa2a` is mandatory. The
  platform does not check whether you set it, so this is on you to get right.
</Note>

**A PDF that already contains signatures is never auto-repaired.** The PdfErrorHandling step that
detects and fixes minor PDF flaws will not modify a document that already has signatures, because
fixing it would invalidate those signatures. The presence of a flaw on an already-signed document
may then surface as a warning or an error depending on which `PdfErrorHandling` mode you choose on
the add-document call (see the `DocumentOptions.PdfOptions.PdfErrorHandling` property in the
[Add document API reference](/docs/nsev/api-reference/documents/add-document)). Plan for the strict modes
(`DetectFail`, `DetectFixFail`) to reject such a document rather than silently accepting it.

**Detected fields are not kept unless you ask.** When you upload a document that was prepared
elsewhere - for example through the Document Portal - and it contains existing signatures, signing
field markers, or form field markers, the resulting document comes back not fully processed: when
you fetch it, `IsActionNeeded` is `true`, and `HasSignatures`, `HasSigningFields` and `HasFormFields`
tell you what was detected. You must explicitly decide what to keep with
`POST /packages/{packageId}/documents/{documentId}/actions` before the document moves to `Draft` and
becomes usable. Two of those choices are mutually exclusive: **you cannot keep existing signatures
and use form fields at the same time**, so `KeepSignatures` and `KeepFormFields` cannot both be
`true` in one request. On the asynchronous add-document call the same `KeepSignatures`,
`KeepSigningFields` and `KeepFormFields` options can be supplied up front under `DocumentOptions`.

**Signature- and text-field names must be alphanumeric.** When you upload a PDF whose existing
signature or text fields were created in another tool, the field names
must contain only letters and numbers. Special characters such as accented letters, slashes and dots
are not supported. Separately, when an uploaded PDF contains text fields whose name matches the Text
Field format configured for your tenant, those text fields are converted to empty signature fields
and the original text field is not displayed - this is intended behaviour, and it does not apply to
documents that already contain one or more signatures.

## An API stakeholder is not a Contact

The API has **no Contact resource**. Contacts exist only in the WebPortal UI, as an address-book
convenience for people who set up packages by hand; when a Contact is used to set up a package it
ultimately becomes an ordinary **person** stakeholder on that package - the same object you create
directly through the API. So when you add a stakeholder via the API you are always defining the
party on the package itself, never referencing a saved address-book entry.

The one place the WebPortal's saved entities surface in the API is the **contactGroup** stakeholder
type, which references a contact *group* by its `ContactGroupCode` - and even that is converted to a
plain **group** stakeholder when the package is activated.

<Note>
  For the full stakeholder/actor model and the three stakeholder types, see
  [The package model → A stakeholder is not a Contact](/docs/nsev/build/concepts/package-model).
</Note>

## The initiator does not need document-group access

A package can be assigned to a document group with `DocumentGroupCode`. In a default configuration an
initiator uploads packages to their personal **My Documents** folder (code `00001`), which is visible
only to that user and cannot be shared. To enable collaboration, an administrator can configure
additional document groups that different users may access, so they can work on one another's
documents.

The surprise is that **the initiator does not need to be a member of, or have permissions on, the
document group the package is assigned to**. To upload to the My Documents folder, omit
`DocumentGroupCode` or set it to `00001`; to upload elsewhere, pass that group's code.

<Note>
  `DocumentGroupCode` is a **string**, even though the values look numeric - the leading zeroes in
  `00001` are part of the value, not formatting. List the configured groups and their codes with
  `GET /documentGroups`. An unknown code returns `404 DocumentGroup.NotFoundWithCode`.
</Note>

## Package and document naming rules

A package `Name` and a document `Name` are both shown in the WebPortal, and the package name is also
used as the file name when the package is downloaded as a `.zip`. Two rules catch people out:

* **Do not add a file extension** to the name value.
* **Avoid forbidden and HTML-sensitive characters.** Do not use file-name characters such as slash
  (`/`), backslash (`\`), question mark (`?`), percent (`%`), asterisk (`*`), colon (`:`), pipe
  (`|`), single quote (`'`), double quote (`"`), less-than (`<`) or greater-than (`>`). This list is
  not exhaustive - also avoid HTML-sensitive characters such as ampersand (`&`) and apostrophe.

Both names are 1–150 characters.

<Note>
  When **itsme** is used as a signing method, restrict the name to characters supported by ISO 8859-15.
  That covers most usual characters, but some software-generated characters - curly apostrophes and
  long dashes, for example - are not supported.
</Note>

## The Web Application Firewall is strict

Requests pass through a Web Application Firewall before they reach the API, and it rejects things the
API itself might otherwise tolerate. Two rules cause most of the surprise:

* **Send strictly valid JSON.** Inline comments, trailing commas, and any other malformed JSON are
  rejected before the API sees them.
* **Send a non-empty `User-Agent` header.** The default user agent for tools like `curl` or `wget`
  may be blocked.

Both are covered in full, with examples, in
[Best Practices](/docs/nsev/build/guides/good-practices).
