# Guarantees

A guarantee (bank guarantee, demand guarantee) is a bank's promise to pay a beneficiary if the applicant doesn't perform: doesn't deliver, doesn't pay back an advance, doesn't finish the work. The beneficiary *claims* (invokes) it to be paid. On Multigate you handle both sides:

- **Inward guarantees:** guarantees issued in your favour (you're the beneficiary). Your bank's SWIFT message (MT760) arrives on Multigate; you check it, complete it and advise it.
- **Outward guarantees:** guarantees you apply for (you're the applicant), for example a performance, advance payment or bid guarantee for a customer. You draft the application, an approver signs it off, and Multigate sends it to your bank.

Read [Trade finance](12-trade-finance.md) first: it explains the permissions, the maker-checker workflow and the conventions these endpoints share (string IDs, `DD/MM/YYYY` dates, no webhooks).

## Before you start

- **The Trade Finance module** for your business, and an API user with the trade finance permissions (see [Who can do what](12-trade-finance.md#who-can-do-what)).
- **`MG_BASE_URL` and `MG_API_KEY`**, as in the [Quickstart](../01-get-started/03-quickstart.md).
- **For outward guarantees:** the beneficiary saved as a [beneficiary](04-beneficiaries.md) (you send its `beneficiaryId`), and your issuing bank's BIC (SWIFT code).

## Find your guarantees

- [List guarantees](api:listGuarantees) returns inward and outward guarantees together.
- [List inward guarantees](api:listInwardGuarantees) and [List outward guarantees](api:listOutwardGuarantees) filter one direction, by status, approval status and date.

Trade finance sends no webhooks. To pick up new inward guarantees and changes, poll the lists and read the details of records that are new or changed. Your users also get an email for each step.

## Inward guarantees

```mermaid
sequenceDiagram
    autonumber
    participant Bank as Advising bank
    participant MG as Multigate
    participant Maker
    participant Checker as Approver
    Bank-)MG: SWIFT MT760
    MG-)Maker: Email "Inward Guarantee Received", status pending
    Maker->>MG: POST /guarantees/inward/{id}/create-instrument
    MG-)Checker: Email "Guarantee Advice Request"
    Checker->>MG: POST /guarantees/inward/{id}/approve
    MG-->>Checker: status advised
```

<Steps>
<Step title="Find the new guarantee">

New inward guarantees arrive with `guaranteeStatus: pending`. Read one with [Get an inward guarantee](api:getInwardGuarantee): the bank's terms (undertaking number, amount, expiry, terms and conditions) and the fields your team fills in. [Download a preview](api:downloadInwardGuaranteePreview) to see it as the bank sent it.

</Step>
<Step title="Complete the instrument (maker)">

[Create the instrument](api:createInwardGuaranteeInstrument) with your internal reference and the fields your team tracks: supplier, discharges, extensions, claims received and settled, fees, material status and what should happen on expiry. Every amount must be in the guarantee's currency. Dates are `DD/MM/YYYY`.

```bash
curl -s -X POST "$MG_BASE_URL/trade-finance-service/api/v1/guarantees/inward/$GUARANTEE_ID/create-instrument" \
  -H "mp-api-key: $MG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "internalInstrumentReference": "IG-2026-0077",
    "supplierName": "Acme Construction Ltd",
    "statusOnExpiry": "extension_required"
  }'
```

- With *manage* only, the guarantee stays `pending` with `approvalStatus: pending`, and approvers get an email.
- An API user that holds *approve* advises it straight away, with no second person.

</Step>
<Step title="Advise or decline (approver)">

An approver [advises the guarantee](api:approveInwardGuarantee) (`advised`) or [declines it](api:declineInwardGuarantee) with a reason of at least 10 characters. Advising records it in your books; nothing is sent to the bank.

</Step>
</Steps>

Like export LCs, a newer version of a guarantee you've advised arrives as a new `pending` record: [merge it into the existing instrument](api:updateInwardGuaranteeInstrument) by its `internalInstrumentReference`. To change your own fields on an advised guarantee, a maker [requests an update](api:requestInwardGuaranteeUpdate) and an approver [approves](api:approveInwardGuaranteeUpdateRequest) or [declines](api:declineInwardGuaranteeUpdateRequest) it.

### Amendments

When the issuing bank amends the guarantee (SWIFT MT767), it moves to `amended` with `hasPendingAmendment: true`. As the beneficiary, you decide whether the new terms apply to you, and your answer goes back to the bank over SWIFT, so two people review it first.

1. A maker [accepts the amendment](api:acceptInwardGuaranteeAmendment) (update this record, or create a new record with its own internal reference) or [refuses it](api:refuseInwardGuaranteeAmendment).
2. An approver [approves the response](api:approveInwardGuaranteeAmendment), which sends it to the bank over SWIFT, or [rejects it](api:rejectInwardGuaranteeAmendment).

After approval the guarantee is `accepted_amendment` or `refused_amendment`. If you chose to create a new record, the new record carries the amended details and the original stays `amended`. If the approver rejects the response, nothing is sent and the guarantee stays `amended`, with `hasPendingAmendment` still `true`, until a maker responds again. Read the guarantee before retrying an approval that timed out: the response may already have gone to the bank.

While an amendment is open, the guarantee is locked: creating or updating its instrument, and raising or approving an update request, fail with "Guarantee has an active amendment request and cannot be modified". Finish the amendment first. `amendment` in the guarantee's details always shows the latest amendment, also after it was answered.

### Claims, extensions and expiry

Multigate keeps the guarantee's working figures up to date from what your team records:

- **Current value:** the amount minus the discharges you record.
- **Unpaid claims:** the claims received minus the claims settled.
- **Ageing:** days left until expiry, using the latest expiry of any extension you record. It's refreshed every night, but only for guarantees that are `pending` or `advised` (inward) or `draft`, `pending` or `applied` (outward); it's also recalculated whenever the record changes.

These figures don't change the status: a guarantee isn't marked expired, claimed or discharged automatically. Record those outcomes in your own fields (`statusOnExpiry`, `materialStatus`, remarks), and set up [expiry reminders](15-trade-finance-dashboard-alerts-reports.md#lifecycle-alerts) so nothing lapses unnoticed.

## Outward guarantees

```mermaid
sequenceDiagram
    autonumber
    participant Maker
    participant MG as Multigate
    participant Checker as Approver
    participant Bank as Issuing bank
    Maker->>MG: POST /guarantees/outward/save (draft)
    Maker->>MG: POST /guarantees/outward/submit
    MG-)Checker: Email "Outward Guarantee Approval Request"
    Checker->>MG: POST /guarantees/outward/{id}/approve
    MG->>Bank: Application
    MG-->>Checker: status applied
    Bank-)MG: Issued
    MG-)Maker: Email "Outward Guarantee Issued", status issued
```

<Steps>
<Step title="Draft the application (maker)">

[Save an outward guarantee application](api:saveOutwardGuaranteeDraft) as a `draft`. Keep the `id` from the response: it's the ID every outward guarantee endpoint takes, and the outward list doesn't return it. To change the draft, save again with that `id` and the **whole** application: fields you leave out are cleared.

The application has what your bank needs to issue the guarantee: its purpose and type (performance, advance payment, tender/bid, warranty…), the form and wording, the amount and currency, the expiry (a fixed date, a condition, or open-ended), the underlying transaction, the applicable rules, your issuing bank's BIC, the charges, and the beneficiary (`beneficiaryId`). Multigate fills in your business's and the beneficiary's details, and the bank names from the BICs.

</Step>
<Step title="Submit it for approval (maker)">

[Submit the application](api:submitOutwardGuarantee) (send `id` to submit a draft). All the required fields are checked now and it becomes `pending`; approvers get an email. There's no idempotency key, so after a timeout, list your outward guarantees before you try again.

</Step>
<Step title="Approve or decline (approver)">

An approver checks it ([Get an outward guarantee](api:getOutwardGuarantee), or as a PDF with [Download an outward guarantee preview](api:downloadOutwardGuaranteePreview)), then [approves it](api:approveOutwardGuarantee) or [declines it](api:declineOutwardGuarantee). The person who submitted it can't approve it. Approving sends the application to your bank and moves it to `applied`. Use approve and decline **only for new applications**: while an amendment or instrument update is waiting, the guarantee also shows `approvalStatus: pending`, and approving it would send the application again. Decide those with the amendment review or instrument update endpoints.

:::danger
If approval fails, read the outward guarantee before trying again: if it's `applied`, the application was sent. Never approve twice without checking, or your bank may receive it twice.
:::

</Step>
<Step title="Wait for the bank to issue it">

When the bank issues the guarantee it moves to `issued`, and makers get an "Outward Guarantee Issued" email.

</Step>
</Steps>

:::warning
**Dates in outward guarantee details are one day late**: each comes back as an ISO timestamp one day after the stored date. Subtract one day until this is fixed.
:::

### Amendments and instrument updates

- **Amendments** change the guarantee's terms with the bank: [submit an amendment](api:submitOutwardGuaranteeAmendment), then an approver [reviews it](api:reviewOutwardGuaranteeAmendment). Approving sends it to the bank (`pending_amendment`); the bank's acceptance (`amended`) and the beneficiary's answer (`accepted_amendment` or `refused_amendment`) arrive later.
- **Instrument updates** change Multigate's record only (internal figures, extensions, claims, discharges, notes): [check eligibility](api:getOutwardGuaranteeInstrumentUpdateEligibility), [save](api:saveOutwardGuaranteeInstrumentUpdateDraft) and [submit](api:submitOutwardGuaranteeInstrumentUpdate) the update, then an approver finds it with [Get the pending instrument update](api:getPendingOutwardGuaranteeInstrumentUpdate) and decides with [Approve an instrument update request](api:approveInstrumentUpdateRequest) or [Decline an instrument update request](api:declineInstrumentUpdateRequest).

Both are only possible while the guarantee is `issued` or `amended` and has no amendment waiting.

## Manual records

Record guarantees handled outside Multigate's SWIFT connection:

- Inward: [save](api:saveInwardGuaranteeUpload) and [submit](api:submitInwardGuaranteeUpload) an uploaded inward guarantee. A new inward upload's response doesn't include its ID: list inward guarantees with `status=draft` (or `pending` after submitting) to find it.
- Outward: [save](api:saveOutwardGuaranteeUploadDraft) and [submit](api:submitOutwardGuaranteeUpload) an uploaded outward guarantee.

You choose the status the record should have; each operation lists the statuses it accepts. An approver approves it like any other record; nothing is sent to a bank.

## Documents

Attach files (PDF, PNG or JPEG, up to 50 MB each) to an inward guarantee (outward guarantees have no document endpoints): [upload one](api:uploadGuaranteeDocument) or [several](api:uploadGuaranteeDocuments), [list them](api:listGuaranteeDocuments), [download one](api:downloadGuaranteeDocument), [get a temporary link](api:getGuaranteeDocumentPublicUrl) (anyone with it can open the file for an hour) or [delete one](api:deleteGuaranteeDocument) permanently.

## Statuses

| Status | Inward | Outward |
|---|---|---|
| `draft` | Manual record being prepared. | Application being prepared. |
| `pending` | Received, not yet advised. | Waiting for an approver. |
| `applied` | | Sent to your bank. |
| `issued` | | Issued by your bank. |
| `advised` | Accepted into your records. | |
| `pending_amendment` | | Amendment sent to the bank. |
| `amended` | Amendment waiting for your response. | Amendment accepted by the bank. |
| `accepted_amendment`, `refused_amendment` | The amendment was accepted or refused. | The beneficiary accepted or refused the amendment. |
| `rejected` | Declined by an approver. | Declined by an approver. |

Other values (`expired`, `claimed`, `discharged`, `under_claim` and similar) are only set on manual records. The full lifecycle is in [Status lifecycles](../06-reference/01-status-lifecycles.md#guarantees).

## Next steps

- [Letters of credit](13-letters-of-credit.md).
- [Dashboard, alerts and reports](15-trade-finance-dashboard-alerts-reports.md): expiry reminders and reports.
- [Email notifications](../03-webhooks-and-emails/04-email-notifications.md#trade-finance).
