Troubleshooting

Diagnose and recover from any failure in the onboarding flow without guessing.

Who this section is for

Anyone hitting an unexpected response from Onboarding-as-a-Service. Errors are organized by the step that produced them.

📘

Scope

The errors below are from the Create an account path's API surface. Errors during the Invite path (failed invitation, rejected acceptance, expired link) are covered under Linked accounts.

Error response shape

PayMongo error responses share the same envelope.

{
  "errors": [
    {
      "code": "parameter_invalid",
      "detail": "Human-readable message explaining what is wrong.",
      "source": { "pointer": "field.path" }
    }
  ]
}

The pointer identifies the offending field. The code is machine-readable; the detail is what to show your engineer (and, after translation, your end user).


Create account

parameter_required on type

{
  "errors": [{
    "code": "parameter_required",
    "detail": "type is required.",
    "source": { "pointer": "type" }
  }]
}

Cause. The Create call omitted the account type.
Fix. Send "type": "merchant" or "type": "consumer" in the request body. The type is permanent for the account.

parameter_invalid on person.email_address or person.mobile_number

Cause. The email is malformed or the mobile number is missing a country code (PH numbers should be in E.164 form, for example +639991234567).
Fix. Validate format on your side and resubmit.

5xx on Create

Cause. Transient PayMongo error.
Fix. Do not blindly retry — first list existing children or look up by email and mobile to confirm whether the account was created despite the error. If it was not, retry with a back-off.


Identity verification

Session expired

Symptom. The hosted identity verification URL returns "session expired" or the API returns verification_session_expired.
Cause. Sessions are valid for 72 hours from creation.
Fix. Create a new verification session and send the new URL to the user.

parameter_invalid on document URLs (API-only flow)

Cause. The provided URL is not HTTPS, is unreachable, or returns a non-image content type.
Fix. Host the image on HTTPS, confirm a 200 OK response with image/jpeg or image/png, then resubmit.

Webhook event has result: failed

{
  "failure_reason": "Please retry. Move closer to the camera, use even lighting, and ensure the face takes up at least half the image height."
}

Cause. The verification was attempted but failed (poor image quality, document not recognized, liveness check failed).
Fix. Show failure_reason to the user and start a new identity verification session. See Best practices — Identity verification for retry guidance. If the failure is blocking a capability request — enabling a wallet, for example — see Liveness check failed on an enable wallet request.

Webhook event has result: invalid

Cause. The submitted data was incomplete or malformed (for example, a secondary ID without the required second secondary document).
Fix. Review the submission, correct the payload, then start a new session.


Update account

parameter_invalid on an enum field

Cause. The provided value is not in the accepted enum list. Common culprits: industry MCC, state code, nature of work, source of funds.
Fix. Look up the accepted values in the Appendix, correct your payload, and PATCH again.

parameter_invalid on person.tin or business.tin

Cause. The TIN format is not recognized.
Fix. Use the canonical format including dashes (for example, 123-456-789-000 for businesses, 123-456-789 for individuals).

"Cannot update activated account"

Cause. The account is already in activation_status: activated. Updates are no longer allowed via the API.
Fix. For most fields, the account holder can edit through the PayMongo Dashboard. For fields locked even there, contact [email protected].


Activate account

parameter_required listing missing fields

{
  "errors": [{
    "code": "parameter_required",
    "detail": "business.industry is required for activation.",
    "source": { "pointer": "business.industry" }
  }]
}

Cause. One or more required-at-activation fields are not set.
Fix. Call Update account to set the listed fields, then call Activate again. See Required information per account type.

merchant.declined / consumer.declined webhook

Cause. Risk review declined the account. The decision is final.
Fix.

  • Show the user a clear message (translate declined_message for your audience; do not show it raw).
  • If you believe the decision was made in error, email [email protected] with the org_* ID and your context.
  • For the user, the typical next step is a new account with corrected information.

Activate returns 200 but no webhook arrives

Cause. Either the activation is still under manual risk review, or your webhook delivery failed.
Fix.

  1. Wait — most automated activations complete in minutes, manual reviews can take up to 14 business days.
  2. Check the PayMongo Dashboard for the account's current activation_status.
  3. Inspect your webhook log for delivery failures and re-deliver if needed.

Acting on behalf of a child (after activation)

resource_not_found with "No such child account"

{
  "errors": [{
    "code": "resource_not_found",
    "detail": "No such child account with id org_incorrectChildID."
  }]
}

Cause. The Account-ID header references an account that is not a child of the authenticated parent.
Fix. Confirm the org_* ID and that the account is linked to your parent. See Linked transactions.

payment_method_not_allowed

Cause. The child does not have the requested payment method enabled.
Fix. Request the capability via Account capabilities, then retry the call.


Capability requests

Enabling a wallet, a payment method, or any other capability is a
capability request. Its own status changes arrive as
capability_request.* events; the identity checks it depends on arrive as
account.identity_verification.* events. Debugging usually means reading both.

Liveness check failed on an enable wallet request

Symptom. You opened prd_svc_paymongo_std_wallet and the request never reaches completed.
Two webhooks tell the story, and they arrive on different event families:

EventFamilyWhat it means
account.identity_verification.failedOnboarding webhooksThe selfie failed the liveness check. failure_reason says why.
capability_request.pending_clarificationCapability requestsThe reviewer is holding the wallet request until a passing selfie exists.

Cause. The wallet capability is granted against a verified authorized representative. A failed
liveness check leaves the account unverified, so the request cannot be provisioned — it is parked
rather than declined, giving you a chance to retry.

Fix.

  1. Read failure_reason from the account.identity_verification.failed payload and show it to
    the user verbatim — it is written as user-facing retry guidance ("move closer to the camera,
    use even lighting…").
  2. Read merchant_note from the capability_request.pending_clarification payload. Check
    merchant_note.requested_files for what the reviewer wants re-uploaded and
    merchant_note.requested_fields for any kyb_data keys to resupply.
  3. Start a new identity verification session — a failed session cannot be reopened. See
    Session expired for the create call and
    Best practices — Identity verification for
    capture guidance that reduces repeat failures.
  4. Wait for account.identity_verification.passed.
  5. If the reviewer asked for kyb_data changes, PATCH /v1/requests/{id} first. Then
    POST /v1/requests/{id}/resubmit. The request returns to under_review and emits
    capability_request.under_review — do not open a second wallet request, it will be
    rejected while the first is still open.
  6. Success path ends at capability_request.processing, then capability_request.completed.
⚠️

Do not retry the capability request instead of the verification

resubmit on its own does nothing about a failed liveness check — the reviewer will park the
request again. The verification has to pass first; resubmit is what tells the reviewer to
look again.

Repeated liveness failures

Cause. Camera quality, lighting, or a representative whose live appearance no longer matches
the submitted ID.
Fix. Switch that user to hosted identity verification
if you are on the API-only flow — it ships the capture microsite, liveness detection, and image
quality checks. After three failed sessions, email
[email protected] with the org_* ID and the verif_* IDs
rather than looping the user through more attempts.

Wallet request went to declined instead

Cause. The reviewer closed the request rather than parking it — typically after repeated
failed verification or an unresolvable mismatch. declined is terminal.
Fix. Read merchant_note.note for the reason. Resolve the underlying issue, then open a new
request. Only PayMongo can reopen a declined one, which arrives as capability_request.submitted
on the same req_ ID.


Webhooks

Events not arriving

Run through, in order:

  1. Confirm the endpoint is registered in the correct scope (test vs. live, parent vs. child).
  2. Confirm your endpoint returns 2xx within the timeout window.
  3. Check the PayMongo Dashboard webhook log for delivery attempts and HTTP status codes.
  4. Re-deliver any failed events from the Dashboard.

Same event received twice

Cause. Normal retry behavior — your handler did not respond 2xx fast enough on the first delivery.
Fix. Implement idempotency on evt_*. See Best practices — Webhooks.

Signature verification fails

Cause. Wrong signing secret, mutated payload (proxy added headers or rewrote JSON), or clock drift on signature timestamp.
Fix.

  • Verify against the raw request body, before any JSON parsing.
  • Use the signing secret listed in the Dashboard for the matching scope (test vs. live).
  • Confirm the request reached your handler unchanged through any reverse proxy.

Where to get more help

  • The relevant Best practices page for the stage you are debugging.
  • Account resource — full field shapes for diagnosing payload errors.
  • Email [email protected] for anything not covered here. Include the org_* ID, the evt_* ID (for webhook issues), and the full error response.

Did this page help you?