eCMRhub.docs

Quickstart for agents

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

  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

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

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:

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

More: Authentication.

2. Check who you are

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

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

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

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

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

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

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

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

ecmrhub drafts issue <draftId> --json

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

{
  "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:

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

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

In a chat client connected through MCP 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.

On this page