Setup accounting integration

How to fetch payroll journal entries from Salsa and export them to your accounting system.

Overview

This guide is for Partners building accounting integrations who need to extract payroll journal data from Salsa and publish it to an external accounting provider. It covers the full workflow: enabling accounting for employers, mapping payroll elements to your chart of accounts, and exporting journal entries after each payroll run.

After running payroll through Salsa, you can:

  1. Fetch journal entries - Get calculated debits/credits for each payroll run
  2. Export to your accounting system - Use the journal data to create entries in your system
  3. Mark as exported - Notify Salsa that the journal has been processed

Each journal entry includes properly categorized line items (wages, taxes, deductions) mapped to your chart of accounts.


Integration Flow

Step 1: Enable Accounting for Employer

Enable accounting integration for each employer:

mutation CreateAccountingConfiguration {
    createAccountingConfiguration(input: {
        employerId: "emp_abc123"
        provider: MANUAL
        workerPaymentExportTrigger: ON_CLEARANCE
    }) {
        accountingConfiguration {
            id
            provider
            workerPaymentExportTrigger
        }
    }
}

Export Trigger Options:

ValueDescription
ON_CLEARANCE(Recommended) Journal ready after payment has cleared. Safer for accounting accuracy.
ON_CONFIRMJournal ready immediately when payroll is confirmed. Faster but may have timing mismatches.

Step 2: Setup Account Mappings

Map payroll elements to your chart of accounts. This determines how journal lines are categorized.

Query Available Mappings

First, query to discover what elements need mapping and get their mappingId values:

query GetMappingRequirements {
    employer(id: "emp_abc123") {
        # Current mapping state (shows mappingId for each element)
        payrollJournalExclusiveAccountMapping {
            bankAccounts {
                mappingId
                bankAccount { id displayName }
                account { id name }  # null if not yet mapped
            }
            pay {
                wages {
                    defaultAccounts { mappingId accountType account { id name } }
                    byPayrollElementType {
                        mappingId
                        payrollElementType { id name }
                        accountType
                        account { id name }
                    }
                }
                reimbursements {
                    defaultAccounts { mappingId accountType account { id name } }
                    byPayrollElementType { mappingId payrollElementType { id name } account { id name } }
                }
            }
            deductions {
                nonTaxes {
                    defaultAccounts { mappingId accountType account { id name } }
                    byPayrollElementType { mappingId payrollElementType { id name } account { id name } }
                }
            }
            contributions {
                taxes {
                    defaultAccounts { mappingId accountType account { id name } }
                    byTax { mappingId tax { id name } accountType account { id name } }
                }
                nonTaxes {
                    defaultAccounts { mappingId accountType account { id name } }
                    byPayrollElementType { mappingId payrollElementType { id name } account { id name } }
                }
            }
        }
    }
}

The response provides:

  • mappingId - Required identifier for each mapping entry
  • accountType - The expected account type (ASSET, EXPENSE, LIABILITY)
  • account - Currently mapped account (null if not yet configured)
  • payrollElementType / tax - The specific element being mapped

Use these mappingId values when setting up mappings.

Configure Account Mappings

Create accounts and map them to payroll elements. Use externalId to store your accounting system's account codes:

mutation UpdatePayrollJournalAccountMapping {
    updatePayrollJournalAccountMapping(input: {
        employerId: "emp_abc123"
        bankAccounts: [
            {
                mappingId: "bank_primary"
                accountReference: {
                    createAccount: {
                        name: "Payroll Clearing Account"
                        type: ASSET
                        externalId: "1000"
                    }
                }
            }
        ]
        pay: {
            wages: {
                mapping: {
                    exclusive: {
                        defaultAccounts: [
                            {
                                mappingId: "wages_expense"
                                accountReference: {
                                    createAccount: {
                                        name: "Wages Expense"
                                        type: EXPENSE
                                        externalId: "6000"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
            reimbursements: {
                mapping: {
                    exclusive: {
                        defaultAccounts: [
                            {
                                mappingId: "reimb_expense"
                                accountReference: {
                                    createAccount: {
                                        name: "Reimbursements Expense"
                                        type: EXPENSE
                                        externalId: "6100"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
        deductions: {
            nonTaxes: {
                mapping: {
                    exclusive: {
                        defaultAccounts: [
                            {
                                mappingId: "deductions_liability"
                                accountReference: {
                                    createAccount: {
                                        name: "Deductions Payable"
                                        type: LIABILITY
                                        externalId: "2100"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
        contributions: {
            taxes: {
                mapping: {
                    exclusive: {
                        defaultAccounts: [
                            {
                                mappingId: "tax_liability"
                                accountReference: {
                                    createAccount: {
                                        name: "Payroll Taxes Payable"
                                        type: LIABILITY
                                        externalId: "2200"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
            nonTaxes: {
                mapping: {
                    exclusive: {
                        defaultAccounts: [
                            {
                                mappingId: "contrib_expense"
                                accountReference: {
                                    createAccount: {
                                        name: "Benefits Expense"
                                        type: EXPENSE
                                        externalId: "6200"
                                    }
                                }
                            },
                            {
                                mappingId: "contrib_expense"
                                accountReference: {
                                    createAccount: {
                                        name: "Liability for 401k Match"
                                        type: LIABILITY
                                        externalId: "6201"
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
    }) {
        employer { id }
        bankAccounts { mappingId account { id name externalId } }
    }
}

Account Types:

TypeUse For
ASSETBank accounts, clearing accounts
EXPENSEWages, reimbursements, employer tax contributions
LIABILITYTax withholdings, deductions payable

Tip: The externalId field is returned in journal entries, making it easy to map to your accounting system.

Mapping Categories:

CategoryDescriptionTypical Account Type
bankAccountsBalancing entry (credit side)ASSET
pay.wagesEmployee compensationEXPENSE
pay.reimbursementsExpense reimbursementsEXPENSE
contributions.taxesEmployer tax contributionsEXPENSE
contributions.nonTaxesNon-tax employer contributions (401k match, etc.)EXPENSE
deductions.nonTaxesEmployee deductions (benefits, garnishments)LIABILITY

Mapping Strategies:

  • defaultAccounts - Use same account(s) for all items in category
  • byPayrollElementType - Specify different accounts per payroll element type
  • byTax - Specify different accounts per tax type (for contributions.taxes)

Step 3: Receive & Export Journals

Webhook Events

You'll receive webhooks when journal transmissions occur:

EventDescription
Transmission.processingJournal generation has started
Transmission.completedJournal is ready to export
Transmission.failedJournal generation failed

Webhook Payload:

{
    "data": {
        "attributes": {
            "category": "LIFECYCLE",
            "createdAt": "2025-12-30T09:32:12.645035",
            "employerId": "emp_123",
            "transmissionId": "trans_xyz789",
            "transmissionType": "ACCOUNTING_PAYROLL_JOURNAL",
            "updatedAt": "2025-12-30T09:32:12.645035"
        },
        "type": "Transmission.completed"
    }
}

Fetch Journal by ID

When you receive a Transmission.completed webhook, use the transmissionId to fetch the journal:

query GetTransmission {
  transmission(id: "trans_xyz789") {
    id
    status
    ... on PayrollJournalManualTransmission {
      journalEntry {
        transactionDate
        totalDebitAmount
        totalCreditAmount
        lines {
          account { accountId name externalId }
          amount
          category
          postingType
        }
      }
      csvDocument { links { url } }
    }
  }
}

Journal Entry Response:

{
  "journalEntry": {
    "transactionDate": "2024-01-15",
    "totalDebitAmount": "10000",
    "totalCreditAmount": "10000",
    "lines": [
      {
        "account": { "accountId": "acct_123", "name": "Wages Expense", "externalId": "6000" },
        "amount": "8000",
        "category": "WAGE",
        "postingType": "DEBIT"
      },
      {
        "account": { "accountId": "acct_456", "name": "Tax Liability", "externalId": "2100" },
        "amount": "2000",
        "category": "TAX_CONTRIBUTION",
        "postingType": "DEBIT"
      },
      {
        "account": { "accountId": "acct_789", "name": "Payroll Bank", "externalId": "1000" },
        "amount": "10000",
        "category": "BANK_ACCOUNT",
        "postingType": "CREDIT"
      }
    ]
  }
}

Line Categories:

CategoryDescription
BANK_ACCOUNTBalancing entry (typically CREDIT)
WAGEEmployee wages
REIMBURSEMENTExpense reimbursements
TAX_CONTRIBUTIONTax amounts
NON_TAX_DEDUCTIONNon-tax deductions
NON_TAX_CONTRIBUTIONNon-tax contributions

Posting Types:

  • DEBIT - Increases assets/expenses, decreases liabilities
  • CREDIT - Decreases assets/expenses, increases liabilities

Mark as Exported

After exporting the journal to your accounting system, mark it as completed:

mutation MarkTransmissionCompleted {
  markTransmissionCompleted(input: {
    transmissionId: "trans_xyz789"
    notFulfilledRequirementIds: [""]
  }) {
    fulfilled {
      id
    }
    notFulfilled {
      id
    }
  }
}

Handle Failed Transmissions

When a transmission fails, you can query for failed requirements and retry them.

Query Failed Requirements:

query GetFailedJournalRequirements {
  employer(id: "emp_abc123") {
    transmissionRequirements(
      filterBy: {
        transmissionType: [ACCOUNTING_PAYROLL_JOURNAL]
        typeSpecificDetails: {
          payrollJournal: {
            latestTransmissionStatuses: [FAILED_TO_TRANSMIT]
          }
        }
      }
      limit: 20
      offset: 0
    ) {
      nodes {
        id
        canBeTransmitted
      }
    }
  }
}

Retry Failed Transmission:

mutation RetryFailedTransmission {
  createTransmissionForRequirements(input: {
    countryISO: USA
    transmissionType: ACCOUNTING_PAYROLL_JOURNAL
    transmissionRequirementIds: ["trmsnreq_xxx"]
  }) {
    transmission {
      id
      ... on PayrollJournalManualTransmission {
        journalEntry {
          transactionDate
          lines { account { name } amount postingType }
        }
        csvDocument { links { url } }
      }
    }
  }
}

CSV Export

Each journal also includes a CSV download option:

query GetTransmissionCSV {
  transmission(id: "trans_xyz789") {
    ... on PayrollJournalManualTransmission {
      csvDocument {
        id
        name
        links {
          url
          expiresAt
        }
      }
    }
  }
}

Use the url from links to download the CSV file. Links have an expiration time (expiresAt).

CSV Format (RFC 4180):

ColumnDescription
Transaction DateJournal entry date
Account IdSalsa account ID
Account NameAccount display name
Account External IdYour external system ID
CategoryLine category (WAGE, TAX_CONTRIBUTION, etc.)
Posting TypeDEBIT or CREDIT
AmountLine amount

Reference: Query Current Configuration

Fetch an employer's accounting setup:

query GetEmployerAccounting {
    employer(id: "emp_abc123") {
        accountingConfiguration {
            id
            provider
            workerPaymentExportTrigger
        }
        accountingAccounts(limit: 100) {
            nodes {
                id
                name
                type
                externalId
            }
        }
    }
}