# Letters of credit

A letter of credit (LC) is a bank's promise to pay a seller once the seller presents the documents the LC asks for. On Multigate you handle both sides:

- **Export LCs:** LCs issued in your favour (you're the seller). Your bank's SWIFT message arrives on Multigate; you check it, complete it and advise it.
- **Import LCs:** LCs you apply for (you're the buyer). 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 import LCs:** the seller saved as a [beneficiary](04-beneficiaries.md) (you send its `beneficiaryId`), and your business's `clientId` from [Get the current user](api:getCurrentUser).

## Find your letters of credit

- [List letters of credit](api:listLettersOfCredit) returns import and export LCs together, newest first.
- [List export letters of credit](api:listExportLettersOfCredit) and [List import letters of credit](api:listImportLettersOfCredit) filter one type, by `status`, `approvalStatus` and creation date.

:::warning
**Export and import LCs use different IDs.** Export LC endpoints take the `lcId`. Import LC endpoints take the record's `id`. Each operation names the ID it expects; take it from that operation's list or detail response.
:::

Trade finance sends no webhooks. To pick up new export LCs and changes, poll the lists (for example every few minutes) and read the details of records that are new or changed. Your users also get an email for each step.

## Export letters of credit

```mermaid
sequenceDiagram
    autonumber
    participant Bank as Advising bank
    participant MG as Multigate
    participant Maker
    participant Checker as Approver
    Bank-)MG: SWIFT MT700
    MG-)Maker: Email "Export LC Created", status pending
    Maker->>MG: POST /letter-of-credits/export/{lcId}/create-instrument
    MG-)Checker: Email "Advice Request", approvalStatus pending
    Checker->>MG: POST /letter-of-credits/export/{lcId}/approve
    MG-->>Checker: status advised
    MG-)Maker: Email "Export LC Approved"
```

<Steps>
<Step title="Find the new export LC">

New export LCs arrive with `lcStatus: pending` and no approval status yet. List them and read the one you want with [Get an export letter of credit](api:getExportLetterOfCredit). The response has the bank's terms (amount, expiry, documents required, shipment details) and the fields your team fills in.

```bash
curl -s "$MG_BASE_URL/trade-finance-service/api/v1/letter-of-credits/export?status=pending" \
  -H "mp-api-key: $MG_API_KEY"
```

To see the LC as the bank sent it, download a PDF with [Download an export LC preview](api:downloadExportLetterOfCreditPreview).

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

[Create the instrument](api:createExportLetterOfCreditInstrument): give the LC your internal reference, the invoice number and value, and any of the internal fields your team tracks (payment schedule, amounts received, supporting documents). Dates are `DD/MM/YYYY`.

```bash
curl -s -X POST "$MG_BASE_URL/trade-finance-service/api/v1/letter-of-credits/export/$LC_ID/create-instrument" \
  -H "mp-api-key: $MG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "internalInstrumentReference": "EXP-2026-0141",
    "invoiceNumber": "INV-88412",
    "instrumentValue": 250000,
    "instrumentExpiryDate": "31/01/2027"
  }'
```

`internalInstrumentReference` must be unique: a reference already used gives `409`.

- An API user with *manage* only leaves the LC `pending` with `approvalStatus: pending`, and approvers get an email.
- An API user that holds *approve* advises it straight away (`lcStatus: advised`), with no second person.

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

An approver [advises the export LC](api:approveExportLetterOfCredit) (`lcStatus` becomes `advised`) or [declines it](api:declineExportLetterOfCredit) with a reason (`rejected`). Advising records the LC as accepted in your books; nothing is sent to the bank.

</Step>
</Steps>

### When the bank sends a newer version

If the bank sends the LC again (an updated MT700 for an LC you've already advised), it arrives as a new `pending` record. Instead of completing it as a second LC, [merge it into the existing instrument](api:updateExportLetterOfCreditInstrument) by sending the existing instrument's `internalInstrumentReference`. With *manage* only, the merge waits for an approver.

### Change your own fields

To change the fields your team owns on an advised export LC (for example amounts received or payment dates), a maker [requests an update](api:requestExportLetterOfCreditUpdate) and an approver [approves](api:approveExportLetterOfCreditUpdateRequest) or [declines](api:declineExportLetterOfCreditUpdateRequest) it. The change only affects Multigate's record.

### Amendments

When the issuing bank amends the LC (SWIFT MT707), the LC moves to `lcStatus: amended` with `hasPendingAmendment: true`, and `amendment` in its details shows the proposed changes.

As the beneficiary, you decide whether the new terms apply to you: under the usual LC rules (ICC UCP 600), an amendment binds the beneficiary only once accepted, and until then the original terms stand. Your answer goes back to the bank over SWIFT, so it is reviewed by two people first.

1. A maker responds: [accept the amendment](api:acceptExportLetterOfCreditAmendment) (choose to update this record, or to create a new record for the amended LC with its own internal reference) or [refuse it](api:refuseExportLetterOfCreditAmendment) with a reason.
2. An approver [approves the response](api:approveExportLetterOfCreditAmendment), which sends your acceptance or refusal to the bank over SWIFT, or [rejects it](api:rejectExportLetterOfCreditAmendment) so the maker can respond again.

After approval the LC is `accepted_amendment` or `refused_amendment`. If you chose to create a new record, the new record is `accepted_amendment` with the amended details and the original stays `amended`. If the approver rejects the response, nothing is sent to the bank and the LC stays `amended`, with `hasPendingAmendment` still `true`, until a maker responds again.

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

:::danger
Approving an amendment response sends a SWIFT message. If the call times out, read the LC before trying again: if its status moved to `accepted_amendment` or `refused_amendment`, the response was sent.
:::

## Import letters of credit

```mermaid
sequenceDiagram
    autonumber
    participant Maker
    participant MG as Multigate
    participant Checker as Approver
    participant Bank as Issuing bank
    Maker->>MG: POST /letter-of-credits/import/save (draft)
    Maker->>MG: POST /letter-of-credits/import/submit
    MG-)Checker: Email "Import LC Approval Request"
    Checker->>MG: POST /letter-of-credits/import/{id}/approve
    MG->>Bank: Application over SWIFT
    MG-->>Checker: status applied
    Bank-)MG: Issued
    MG-)Maker: Email "Import LC Issued", status issued
```

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

[Save an import LC application](api:saveImportLetterOfCredit) as a `draft` while you fill it in. Keep `data.id` from the response: it's the ID every import LC endpoint takes. To change the draft, save again with that `id` and the **whole** application: fields you leave out are cleared. Nothing is checked for completeness until you submit.

The application has the terms you'd give your bank: amount and currency, how the LC is available (payment, acceptance, negotiation…), the advising and available-with banks, the seller (`beneficiaryId`), shipment details, the documents required and the expiry date. Multigate fills in your business's details, the beneficiary's details and the bank names from the IDs and codes you send.

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

[Submit the application](api:submitImportLetterOfCredit) (send `id` to submit a draft). All the required fields are checked now, and the application becomes `pending`. Approvers get an email.

There's no idempotency key: if a submit times out, [list your import LCs](api:listImportLettersOfCredit) before you try again, or you may create a second application.

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

An approver reads the application ([Get an import LC](api:getImportLetterOfCredit), or as the bank will see it with [Preview an import LC](api:previewImportLetterOfCredit)), then [approves it](api:approveImportLetterOfCredit) or [declines it](api:declineImportLetterOfCredit) with a reason. The person who submitted it can't approve it.

Approving sends the application to your bank over SWIFT and moves it to `applied`. Use approve and decline **only for new applications**: while an amendment or instrument update is waiting, the LC also shows `approvalStatus: pending`, and approving it would send the application to the bank again. Decide those with the amendment review or instrument update endpoints.

:::danger
If approval times out or fails with `502`, the application **may still have reached the bank**: Multigate can't tell a bank timeout from a refusal. Read the import LC first. If it's `applied`, it was sent. If it's still `pending`, contact Multigate before approving again, or your bank may receive the application twice.
:::

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

When the bank issues the LC, its status moves to `issued` and makers get an "Import LC Issued" email. Poll [Get an import LC](api:getImportLetterOfCredit) (or the list) to see it.

</Step>
</Steps>

:::warning
**Dates in import LC responses are one day late.** Each date comes back as an ISO timestamp one day after the stored date (an expiry stored as 31 January 2027 comes back as `2027-02-01T00:00:00.000Z`). Subtract one day until this is fixed.
:::

### Amendments

To change the terms of an issued LC (for example increase the amount or extend the shipment date), a maker [submits an amendment](api:submitImportLetterOfCreditAmendment) with only the fields that change and the amendment date. An approver [reviews it](api:reviewImportLetterOfCreditAmendment): approving sends it to the bank over SWIFT (status `pending_amendment`), declining discards it.

The bank's and the seller's answers arrive later: `amended` when the bank accepts it, then `accepted_amendment` or `refused_amendment` when the seller (beneficiary) responds. The same retry rule applies as for approval: read the LC before reviewing again.

### Instrument updates

To change Multigate's record of an issued LC without telling the bank (for example an internal reference, payment dates or notes):

1. Check the LC can be updated: [Check instrument update eligibility](api:getImportLetterOfCreditInstrumentUpdateEligibility).
2. A maker [saves](api:saveImportLetterOfCreditInstrumentUpdate) and [submits](api:submitImportLetterOfCreditInstrumentUpdate) the update, either to change this record or to create a new record from it.
3. An approver finds it with [Get the pending instrument update](api:getPendingImportLetterOfCreditInstrumentUpdate) and decides with [Approve an instrument update request](api:approveInstrumentUpdateRequest) or [Decline an instrument update request](api:declineInstrumentUpdateRequest).

## Manual records

Use manual uploads to record LCs handled outside Multigate's SWIFT connection, so all your instruments are in one place:

- Export: [save](api:saveUploadedExportLetterOfCredit) and [submit](api:submitUploadedExportLetterOfCredit) an uploaded export LC.
- Import: [save](api:saveUploadedImportLetterOfCredit) and [submit](api:submitUploadedImportLetterOfCredit) an uploaded import LC.

You choose the status the record should have (for example `issued` or `settled`). An approver approves it like any other record; nothing is sent to a bank. Approvers get a "Trade Finance Record Upload - Approval Required" email.

## Documents

Attach invoices, bills of lading, certificates and other files (PDF, PNG or JPEG, up to 50 MB each) to an export LC. Import LCs have no document endpoints.

- [Upload a document](api:uploadLetterOfCreditDocument) or [several at once](api:uploadLetterOfCreditDocuments).
- [List an LC's documents](api:listLetterOfCreditDocuments), [download one](api:downloadLetterOfCreditDocument) or [get a temporary link](api:getLetterOfCreditDocumentPublicUrl) to share it (anyone with the link can open it for an hour).
- [Delete a document](api:deleteLetterOfCreditDocument). Deleting is permanent.

Send document IDs in `supportingDocumentIds` when you create or update the instrument to list them on the LC.

## Statuses

| `lcStatus` | Meaning |
|---|---|
| `draft` | Import application or manual record being prepared. |
| `pending` | Export LC received and not yet advised, or import application waiting for an approver. |
| `applied` | Import application sent to your bank. |
| `issued` | The bank has issued the import LC. |
| `advised` | Export LC accepted into your records. |
| `pending_amendment` | Import LC amendment sent to the bank. |
| `amended` | An amendment is waiting for a response (export) or the bank accepted it (import). |
| `accepted_amendment`, `refused_amendment` | The amendment was accepted or refused. |
| `rejected` | Declined by an approver. |

Other values (`processing`, `documents_discrepant`, `documents_rejected`, `documents_accepted`, `partially_settled`, `settled`, `closed`) are only set on manual records. `approvalStatus` (`pending`, `approved`, `rejected`) shows whether something is waiting for an approver. The full lifecycle is in [Status lifecycles](../06-reference/01-status-lifecycles.md#letters-of-credit).

## Errors and recovery

| Response | Meaning | What to do |
|---|---|---|
| `400` with a list of fields | A field is missing or invalid, for example a date not in `DD/MM/YYYY`. | Fix the fields and send again. |
| `400` "Cannot approve a rejected Letter of Credit", "… is not pending approval" | The record isn't in the right status for this step. | Read the record and follow its current status. |
| `403` `forbidden` | Your API user lacks the permission, or (for approvals) submitted the request itself. | Use an API user with the right permission; another person must approve. |
| `404` | The ID is wrong, or it's the other kind of ID (`lcId` vs `id`). | Take the ID from the list or detail response of the same LC type. |
| `409` "Internal instrument reference already exists" | Another record uses the reference. | Choose another reference. |
| `500` | Also returned for an ID that isn't a number. | Check the ID. Otherwise quote the reference ID in the message to support. |
| `502` on approve or amendment review | The call to the bank failed or timed out; the record didn't change, but the instruction may have reached the bank. | Read the record; if it's unchanged, contact Multigate before trying again. |

## Next steps

- [Guarantees](14-guarantees.md).
- [Dashboard, alerts and reports](15-trade-finance-dashboard-alerts-reports.md): reminders before LC expiry and instalment due dates.
- [Email notifications](../03-webhooks-and-emails/04-email-notifications.md#trade-finance).
