Event Types

See below for a list of all webhook event categories and associated payloads.

Event Categories

Account Balance Activity

CategoryPayload TypeDescriptionTrigger
mural_account_balance_activityaccount_creditedFunds received in a Mural accountIncoming blockchain transaction confirmed
mural_account_balance_activityaccount_debitedFunds sent from a Mural accountOutgoing blockchain transaction confirmed

Account Credited

interface AccountCreditedPayload {
  type: 'account_credited';
  accountId: string;
  organizationId: string;
  transactionId: string; // this is the id that will appear in the Transactions API
  accountWalletAddress: string;
  tokenAmount: {
    blockchain: string;
    tokenAmount: number;
    tokenSymbol: string;
    tokenContractAddress: string;
  };
  transactionDetails: {
    blockchain: string;
    transactionDate: string; // ISO 8601 datetime
    transactionHash: string;
    sourceWalletAddress: string;
    destinationWalletAddress: string;
  };
}

Account Debited

interface AccountDebitedPayload {
  type: 'account_debited';
  accountId: string;
  organizationId: string;
  transactionId: string; // this is the id that will appear in the Transactions API
  accountWalletAddress: string;
  tokenAmount: {
    blockchain: string;
    tokenAmount: number;
    tokenSymbol: string;
    tokenContractAddress: string;
  };
  transactionDetails: {
    blockchain: string;
    transactionDate: string; // ISO 8601 datetime
    transactionHash: string;
    sourceWalletAddress: string;
    destinationWalletAddress: string;
  };
}

Payout Request

CategoryPayload TypeDescriptionTrigger
payout_requestpayout_request_status_changedPayout request status has changedPayout request transitions to a new status
payout_requestpayout_status_changedIndividual payout status has changedFiat or blockchain payout transitions to a new status

Payout Request Status Changed Payload

This event is triggered when the overall payout request status changes. A payout request may contain multiple individual payouts (recipients).

interface PayoutRequestStatusChangedPayload {
  type: 'payout_request_status_changed';
  organizationId: string;
  payoutRequestId: string;
  statusChangeDetails: {
    previousStatus: PayoutRequestStatus;
    currentStatus: PayoutRequestStatus;
  };
}

type PayoutRequestStatus =
  | { type: 'awaitingExecution' } // Payout request created, awaiting blockchain execution
  | { type: 'pending' } // Blockchain transaction submitted, payouts in progress
  | { type: 'executed' } // All payouts completed successfully
  | { type: 'failed' } // One or more payouts failed
  | { type: 'canceled' }; // Payout request was canceled

Example Payload

{
  "type": "payout_request_status_changed",
  "organizationId": "e77ee023-fa9a-4d42-9be9-74f3a2bb2042",
  "payoutRequestId": "a3d9f1b2-7c4e-4a6f-9b1d-2e8c5f7a9d30",
  "statusChangeDetails": {
    "previousStatus": { "type": "awaitingExecution" },
    "currentStatus": { "type": "pending" }
  }
}

Payout Status Changed Payload

This event is triggered when an individual payout's status changes. The statusChangeDetails object contains payout type and status information, where type indicates whether this is a fiat (bank transfer) or blockchain payout.

interface PayoutStatusChangedPayload {
  type: 'payout_status_changed';
  organizationId: string;
  payoutRequestId: string;
  payoutId: string;
  statusChangeDetails: FiatPayoutStatusChangeDetails | BlockchainPayoutStatusChangeDetails;
}

// Fiat payout status change details (bank transfers)
interface FiatPayoutStatusChangeDetails {
  type: 'fiat';
  previousStatus: FiatPayoutStatus;
  currentStatus: FiatPayoutStatus;
}

// Blockchain payout status change details
interface BlockchainPayoutStatusChangeDetails {
  type: 'blockchain';
  previousStatus: BlockchainPayoutStatus;
  currentStatus: BlockchainPayoutStatus;
}

// Fiat payout statuses - objects with type field
type FiatPayoutStatus =
  | { type: 'created' } // Payout created, awaiting processing
  | { type: 'pending' } // Payout submitted to provider
  | { type: 'onHold' } // Payout on hold (compliance review)
  | { type: 'completed' } // Funds delivered successfully
  | { type: 'failed' } // Payout failed
  | { type: 'canceled' } // Payout was canceled
  | { type: 'refundInProgress' } // Refund is being processed
  | { type: 'refunded' }; // Funds refunded to source account

// Blockchain payout statuses - objects with type field
type BlockchainPayoutStatus =
  | { type: 'awaitingExecution' } // Awaiting blockchain transaction
  | { type: 'pending' } // Transaction submitted to blockchain
  | { type: 'executed' } // Transaction confirmed on blockchain
  | { type: 'failed' } // Transaction failed
  | { type: 'canceled' }; // Payout was canceled

Example Fiat Payout Payload

{
  "type": "payout_status_changed",
  "organizationId": "e77ee023-fa9a-4d42-9be9-74f3a2bb2042",
  "payoutRequestId": "a3d9f1b2-7c4e-4a6f-9b1d-2e8c5f7a9d30",
  "payoutId": "b4e8c2d1-5f6a-4b7c-8d9e-1a2b3c4d5e6f",
  "statusChangeDetails": {
    "type": "fiat",
    "previousStatus": { "type": "created" },
    "currentStatus": { "type": "pending" }
  }
}

Example Blockchain Payout Payload

{
  "type": "payout_status_changed",
  "organizationId": "e77ee023-fa9a-4d42-9be9-74f3a2bb2042",
  "payoutRequestId": "a3d9f1b2-7c4e-4a6f-9b1d-2e8c5f7a9d30",
  "payoutId": "c5f9d3e2-6a7b-4c8d-9e1f-2b3c4d5e6f7a",
  "statusChangeDetails": {
    "type": "blockchain",
    "previousStatus": { "type": "pending" },
    "currentStatus": { "type": "executed" }
  }
}

Payin

CategoryPayload TypeDescriptionTrigger
payinpayin_status_changedPayin status has changedPayin is created, or transitions to a new status

Payin Status Changed Payload

This event is triggered when a payin is created and whenever its status subsequently changes. The previousStatus field is null only on the initial creation event; for all subsequent transitions, it holds the prior status.

interface PayinStatusChangedPayload {
  type: 'payin_status_changed';
  organizationId: string;
  payinId: string;
  statusChangeDetails: {
    previousStatus: PayinStatus | null; // null on initial creation
    currentStatus: PayinStatus;
  };
}

type PayinStatus =
  | { type: 'created' }
  | { type: 'pending' }
  | { type: 'on-hold' }
  | { type: 'completed' }
  | { type: 'failed' }
  | { type: 'canceled' };

Fetch full payin detail (including timestamps and the reason on failure) from GET /payins/{payinId}.

Example Creation Payload

{
  "type": "payin_status_changed",
  "organizationId": "e77ee023-fa9a-4d42-9be9-74f3a2bb2042",
  "payinId": "d192b782-647c-4011-8184-ab9c1e1b5b3d",
  "statusChangeDetails": {
    "previousStatus": null,
    "currentStatus": { "type": "created" }
  }
}

Example Transition Payload

{
  "type": "payin_status_changed",
  "organizationId": "e77ee023-fa9a-4d42-9be9-74f3a2bb2042",
  "payinId": "d192b782-647c-4011-8184-ab9c1e1b5b3d",
  "statusChangeDetails": {
    "previousStatus": { "type": "pending" },
    "currentStatus": { "type": "completed" }
  }
}

Business Verification

CategoryPayload TypeDescriptionTrigger
business_verificationverification_status_changedBusiness verification status has been updatedKYC/KYB review completed or status change occurred

Verification Status Changed Payload

interface BusinessVerificationStatusChangedPayload {
  type: 'verification_status_changed';
  organizationId: string;
  previousStatus: MuralKycVerificationStatus;
  currentStatus: MuralKycVerificationStatus;
  verificationId: string;
  updatedAt: string; // ISO 8601 datetime
}

// Status objects returned based on verification state
type MuralKycVerificationStatus =
  | { type: 'inactive' }
  | { type: 'pending' }
  | { type: 'approved'; approvedAt: string }
  | { type: 'errored'; details: string; erroredAt: string }
  | { type: 'rejected'; reason: string; rejectedAt: string };

Example Status Objects

Inactive Status:

{ "type": "inactive" }

Pending Status:

{ "type": "pending" }

Approved Status:

{
  "type": "approved",
  "approvedAt": "2024-03-21T10:30:00Z"
}

Errored Status:

{
  "type": "errored",
  "details": "Verification encountered an error",
  "erroredAt": "2024-03-21T10:30:00Z"
}

Rejected Status:

{
  "type": "rejected",
  "reason": "Verification was rejected",
  "rejectedAt": "2024-03-21T10:30:00Z"
}

Organization Terms of Service

CategoryPayload TypeDescriptionTrigger
organization_tostos_acceptedOrganization accepted Terms of ServiceInitial TOS acceptance by organization

TOS Accepted Payload

interface OrganizationTosAcceptedPayload {
  type: 'tos_accepted';
  organizationId: string;
  signedAt: string; // ISO 8601 datetime
  source: 'ui' | 'api' | 'test';
}

Source Field Values

  • ui: TOS was accepted through the Mural web application by an authenticated user
  • api: TOS was accepted via the public REST API endpoint
  • test: TOS event was triggered as a test webhook

Example Payload

{
  "type": "tos_accepted",
  "organizationId": "e77ee023-fa9a-4d42-9be9-74f3a2bb2042",
  "signedAt": "2024-03-21T10:30:00Z",
  "source": "ui"
}

Note: This event is only sent on initial TOS acceptance. Re-signing or updating agreements will not trigger additional webhook events.


Compliance Review

CategoryPayload TypeDescriptionTrigger
compliance_reviewcompliance_review_status_changedCompliance review status has changedCompliance review transitions to a new status

Compliance Review Status Changed Payload

This event is triggered whenever a compliance review (individual or business) transitions to a new status — for example when a draft is submitted, when a submitted review moves into review, or when a review reaches a terminal approved, rejected, or error state.

The organizationId identifies the organization that owns the compliance review; for organizations with a parent/child structure this may be a parent or child organization. Both previousStatus and currentStatus use the same discriminated-union shape returned by GET /compliance/reviews/{complianceReviewId}.

interface ComplianceReviewStatusChangedPayload {
  type: 'compliance_review_status_changed';
  organizationId: string;
  complianceReviewId: string;
  previousStatus: ComplianceReviewStatus;
  currentStatus: ComplianceReviewStatus;
  updatedAt: string; // ISO 8601 datetime
}

// Status is an object with a type discriminator; some variants carry extra fields
type ComplianceReviewStatus =
  | { type: 'draft' } // Review created, awaiting attestation uploads
  | { type: 'submitted'; submittedAt: string } // Submitted; submission validations will begin shortly
  | { type: 'validatingSubmission' } // Submission validations are currently running
  | { type: 'submissionValidationsFailed' } // One or more submission validations failed
  | { type: 'inReview'; submittedAt: string } // Currently being evaluated
  | { type: 'additionalInformationRequested' } // More information required before the review can proceed
  | { type: 'approved'; submittedAt: string; approvedAt: string } // Approved; requested KYC tier granted
  | {
      type: 'rejected';
      submittedAt: string;
      rejectedAt: string;
      rejectionDescription: string; // Reason the review was rejected
    }
  | {
      type: 'error';
      submittedAt: string;
      errorDescription: string; // Description of the processing error
    };

Status Field Notes

  • submittedAt is present on submitted, inReview, approved, rejected, and error. It is absent on draft, validatingSubmission, and submissionValidationsFailed.
  • approvedAt / rejectedAt are populated only once the review reaches the corresponding terminal state.
  • rejectionDescription is populated only on the rejected status.
  • errorDescription is populated only on the error status.

Fetch full compliance review detail (tier, type, attestations, and additional metadata) from GET /compliance/reviews/{complianceReviewId}.

Example Submission Payload

{
  "type": "compliance_review_status_changed",
  "organizationId": "org_abc123",
  "complianceReviewId": "review_xyz789",
  "previousStatus": { "type": "draft" },
  "currentStatus": {
    "type": "submitted",
    "submittedAt": "2026-02-24T12:00:00.000Z"
  },
  "updatedAt": "2026-02-24T12:00:00.000Z"
}

Example Approval Payload

{
  "type": "compliance_review_status_changed",
  "organizationId": "org_abc123",
  "complianceReviewId": "review_xyz789",
  "previousStatus": {
    "type": "inReview",
    "submittedAt": "2026-02-24T12:00:00.000Z"
  },
  "currentStatus": {
    "type": "approved",
    "submittedAt": "2026-02-24T12:00:00.000Z",
    "approvedAt": "2026-02-25T10:30:00.000Z"
  },
  "updatedAt": "2026-02-25T10:30:00.000Z"
}

Example Rejection Payload

{
  "type": "compliance_review_status_changed",
  "organizationId": "org_abc123",
  "complianceReviewId": "review_def456",
  "previousStatus": {
    "type": "inReview",
    "submittedAt": "2026-02-24T12:00:00.000Z"
  },
  "currentStatus": {
    "type": "rejected",
    "submittedAt": "2026-02-24T12:00:00.000Z",
    "rejectedAt": "2026-02-25T10:30:00.000Z",
    "rejectionDescription": "Provided information does not meet KYC requirements."
  },
  "updatedAt": "2026-02-25T10:30:00.000Z"
}

Example Error Payload

{
  "type": "compliance_review_status_changed",
  "organizationId": "org_abc123",
  "complianceReviewId": "review_def456",
  "previousStatus": {
    "type": "inReview",
    "submittedAt": "2026-02-24T12:00:00.000Z"
  },
  "currentStatus": {
    "type": "error",
    "submittedAt": "2026-02-24T12:00:00.000Z",
    "errorDescription": "Verification provider returned an unexpected error."
  },
  "updatedAt": "2026-02-25T10:30:00.000Z"
}