File Operations

Process inbound Fedwire files and generate outbound ones

Overview

Every Fedwire message is one ISO 20022 envelope in one file. Twisp processes the files you receive one at a time. It writes the messages you send as separate files in one tar.gz archive per generation.

OperationGraphQLWhat it does
UploadMutation.files.createUpload()Get a URL to upload an inbound file
ProcessMutation.wire.processFile()Record an inbound message and apply it
GenerateMutation.wire.generateFile()Write every queued outbound message to one archive
DownloadMutation.files.createDownload()Fetch a generated archive
InspectQuery.wire.file(), Query.wire.message()Read a file, its messages and their outcome

Processing Inbound Files

1. Upload

Upload the file exactly as the sponsor bank delivered it, with upload type WIRE and content type application/xml:

mutation UploadWireFile {
  files {
    createUpload(
      input: {
        key: "wires/inbound/20261009-000123.xml"
        uploadType: WIRE
        contentType: "application/xml"
      }
    ) {
      uploadURL
      uploadHeaders
    }
  }
}

PUT the file to uploadURL with uploadHeaders.

2. Process

mutation ProcessWireFile {
  wire {
    processFile(
      input: {
        configId: "5d1c6a0e-8b7f-4e2a-9c3d-2e1f0a9b8c7d"
        fileKey: "wires/inbound/20261009-000123.xml"
      }
    ) {
      fileId
      status
      messages(first: 1) {
        nodes {
          messageId
          kind
          msgId
          uetr
          status
        }
      }
    }
  }
}

processFile parses the envelope and records the file and its message, then returns. The message is applied asynchronously:

  • A credit transfer (pacs.008, pacs.009) is decided and posted as an inbound wire.
  • A payment status (pacs.002), message reject (admi.002) or payment return (pacs.004) is applied to the outbound wire it answers.
  • Other messages, such as a camt.056 return request or a Fed broadcast, are recorded with no action.

processFile fails with BAD_REQUEST when the file is not a Fedwire envelope from the Fed: the wrong root element or namespace, an outgoing-to-Fed envelope, no message or more than one, or an amount that is not a whole number of cents.

Processing Twice

Processing is idempotent:

  • Processing the same file key again returns the earlier file and changes nothing.
  • A message already recorded under another key is recorded as a new file with no messages and a detail naming the earlier message. It is not applied again.
  • A credit transfer whose UETR an earlier wire already has is recorded as IGNORED.

Following a Message

Read the message to see its outcome:

query WireMessage {
  wire {
    message(messageId: "0b9e44a2-6d0c-5b3e-9f1a-2c3d4e5f6a7b") {
      kind
      status
      detail
      executionId
    }
  }
}
Message statusMeaning
RECEIVEDRecorded; not yet applied
PROCESSEDApplied: posted, or applied to its outbound wire. detail says how, such as settle or returned AC03.
IGNOREDRecorded with no action: a duplicate, a reply for a wire that no longer accepts it, or a message type Twisp does not act on
ERRORCould not be applied. detail gives the reason.
GENERATEDAn outbound message written to a generation's archive

executionId is the workflow execution the message belongs to. For an inbound credit transfer it is the WIRE_INBOUND execution, whose id equals the message id.

Generating Outbound Files

Wires you send (WIRE_OUTBOUND executions in CREATE) and inbound wires you return wait in queues. generateFile writes them to one tar.gz archive at the fileKey you give:

mutation GenerateWireFile {
  wire {
    generateFile(
      input: {
        configId: "5d1c6a0e-8b7f-4e2a-9c3d-2e1f0a9b8c7d"
        fileKey: "wires/outbound/2026-10-09T15-00.tar.gz"
      }
    ) {
      generated
      file {
        fileId
        fileKey
        messageCount
        totalAmount
        messages(first: 100) {
          edges {
            node {
              kind
              msgId
              uetr
            }
          }
        }
      }
    }
  }
}

For each queued item, generateFile:

  1. Gives the message the next IMAD.
  2. Builds a pacs.008 for an outbound wire, or a pacs.004 for a returned inbound wire, and checks it against the Fed usage guidelines.
  3. Adds it to the archive as its own file.
  4. Moves an outbound wire to SUBMIT.

Wires cancelled or rejected while queued are skipped. When nothing is queued, generated is false and no archive is written.

generateFile is idempotent by fileKey. If a key was already generated for the configuration, generateFile returns that generation and writes nothing. Use a new key for each generation, such as one with the time in it. If a call fails, or you do not get its response, call again with the same key: you get the generation if it was written, or a new one if it was not.

Archive Layout

The archive holds one file per message, in IMAD order:

000001_customer_credit_transfer_<uetr>.xml
000002_customer_credit_transfer_<uetr>.xml
000003_payment_return_<uetr>.xml

Each file is one Fedwire envelope. Forward each one to the sponsor bank as its own file. The number at the start is the message's position plus one. The generation's messages, with their IMADs, UETRs and amounts, are also on Query.wire.file().

The archive is complete when generateFile returns. If a generation fails, its wires stay queued, and the next generateFile writes them with the same IMADs. A failed generation can leave an archive at its key. Do not forward it: the archive at a key is valid only after generateFile returns that key with generated: true. A retry with the key replaces the archive.

Downloading

Get a presigned download URL for the archive with Mutation.files.createDownload():

mutation DownloadWireFile {
  files {
    createDownload(key: "wires/outbound/2026-10-09T15-00.tar.gz") {
      downloadURL
      downloadURLExpiration
    }
  }
}

File Statuses

StatusMeaning
PROCESSINGAn inbound file whose message is being applied
PROCESSEDAn inbound file whose message has an outcome
ERRORAn inbound file whose message could not be applied
GENERATEDAn outbound generation whose archive is written
Previous
Configuration