# Quickstart for agents (https://docs-ecmrhub-v2.lucaspiera.com/docs/quickstart)

> Sign in, learn the fields, create a draft and issue it after a person approves. Written for an AI agent working for one company.

> **In build (CLI, OAuth and approvals):** The `ecmrhub` CLI, OAuth sign-in and approvals are part of phase 1 and not released yet. The steps
> below follow the agreed contract; run `ecmrhub --help` for the exact flags of your version.

You are an agent working for one company. Everything you do happens in that company's account,
within the permissions the company granted you. Follow these steps in order.

## Rules before you start [#rules-before-you-start]

1. **Never guess data.** Names, addresses, plates, dates and goods come from the user or from a
   source document. If a required value is missing, ask.
2. **Never approve for the user.** When Hub answers `APPROVAL_REQUIRED`, give the person the
   approval link and wait. There is no flag or tool that approves.
3. **Repeat exactly.** After approval, repeat the same call with the same input plus the approval
   id. Any change of input needs a new approval.
4. **Use JSON.** Pass `--json` (or pipe the output) and parse stdout. Errors arrive on stderr as
   `{"error":{"status","code","message","retryable"}}`. Decide by `code`; messages may be in Polish.
5. **eFTI gaps do not block issuing.** Report them to the user; never promise eFTI registration.

## 1. Sign in [#1-sign-in]

Ask the user to run the sign-in once, or run it if you have a terminal and the user is present:

```bash
ecmrhub login
```

It opens the browser. The person signs in to Hub, and the company owner chooses what you may do
(read documents, write drafts, signing links...) and whether issuing needs their approval. Tokens are stored in
`~/.config/ecmr-hub/config.json` (mode 0600) and refreshed automatically.

In CI or scripts use a company API key instead, never on the command line:

```bash
export ECMR_HUB_API_KEY=ecmr_sk_...   # from the dashboard, API keys
```

More: [Authentication](https://docs-ecmrhub-v2.lucaspiera.com/docs/authentication.md).

## 2. Check who you are [#2-check-who-you-are]

```bash
ecmrhub whoami --json
```

Read the company and `permissions`. If a permission you need is missing, tell the user which one;
only a person in the dashboard can grant it.

## 3. Learn the fields [#3-learn-the-fields]

```bash
ecmrhub fields --json
```

Each field has a `key`, whether it is `required` to issue, whether eFTI needs it
(`eftiRequired`) and, for coded fields, the allowed `codes`. Values are strings, dates are
`YYYY-MM-DD`, countries are ISO 3166 alpha-2 codes.

## 4. Check the data locally [#4-check-the-data-locally]

Write the values as one flat JSON object keyed by field keys, then:

```bash
ecmrhub drafts check --data note.json --json
```

Repeat until `ok` is `true`. The report lists `errors`, `missingRequired` and `eftiGaps`. The
check runs locally and sends nothing.

## 5. Create the draft [#5-create-the-draft]

```bash
ecmrhub drafts create --data note.json --json
```

It returns the draft `id` and `revision`. To fix something, send only the changed fields:

```bash
ecmrhub drafts update <draftId> --data changes.json --json
```

An empty string clears a field. A `409 VERSION_CONFLICT` means the draft changed meanwhile: list
drafts, read it again, retry.

## 6. Issue it, with approval [#6-issue-it-with-approval]

Issuing creates an immutable document, so a person approves it first:

```bash
ecmrhub drafts issue <draftId> --json
```

The first call exits with code `5` and prints the pending approval:

```json
{
  "error": {
    "status": 428,
    "code": "APPROVAL_REQUIRED",
    "message": "...",
    "retryable": false,
    "approval": {
      "id": "6f1c...",
      "url": "https://ecmrhub-v2.lucaspiera.com/dashboard/approvals/6f1c...",
      "expiresAt": "2026-10-20T10:00:00Z",
      "operation": "draft.publish",
      "retry": "ecmrhub drafts issue <draftId> --revision 3 --approval 6f1c... --json"
    }
  }
}
```

Tell the user: "Please approve issuing this consignment note: `<url>`". Then wait, and run the
command from `error.approval.retry` exactly as given:

```bash
ecmrhub approvals wait <approvalId> --json   # 0 approved, 4 rejected, 1 expired or used, 5 still pending
ecmrhub drafts issue <draftId> --revision 3 --approval <approvalId> --json
```

Issuing the same draft again returns the same document, so a retry after a timeout is safe.

## 7. After issuing [#7-after-issuing]

```bash
ecmrhub sign request <documentId> --role carrier --json   # needs approval too
ecmrhub documents pdf <documentId> --out note.pdf          # hash-checked PDF
ecmrhub documents evidence <documentId> --json             # versions, events, signatures
ecmrhub efti check <documentId> --json                     # eFTI gaps, nothing is sent
```

Send a signing link only to the party it is for. It is valid for 7 days.

## The same flow over MCP [#the-same-flow-over-mcp]

In a chat client connected through [MCP](https://docs-ecmrhub-v2.lucaspiera.com/docs/mcp.md) the steps are tools: `draft_save`,
`draft_publish`, `signing_createLink` and so on. A tool that needs approval returns
`status: "approval_required"` with `approvalId` and `url` in its result. Show the link to the user,
and after they approve call the same tool with the same arguments plus `approvalId`.
