Capability requests API

Open, correct, and track a capability request over the API — the endpoints, what to send per product, how to attach documents, and what a parent platform can do for its fully managed children.

Who this section is for

Developers who open capability requests over the API instead of the merchant dashboard —
activating a payment method (GCash, Maya, GrabPay, ShopeePay, cards), filing a tax document, or
changing the business profile.

A capability request is an application to turn something on for an account. PayMongo reviews
it, and the request moves through a fixed set of statuses. Every status change is also pushed as
a webhook event — those payloads live in
Capability request webhooks.

Before you begin

🚧

Prerequisites

  1. Authenticate with the account's secret key using HTTP Basic auth
    (Authorization: Basic base64(sk_xxx:)). A parent acting on a child uses its own secret key
    plus the Account-ID header — see Requests on linked accounts.
  2. Activate the account. Payment method, tax document and account update requests are rejected
    with 400 until the account has completed activation.
  3. Register a webhook endpoint if you want to be told when review finishes — see
    Setup & Management.
  4. Use the same mode (sk_test_… / sk_live_…) as the webhook you registered. The key used on
    POST /v1/requests fixes the livemode of every event that request goes on to emit.

Base URL: https://api.paymongo.com.

Endpoints

CallBodyNew statusEvent emitted
POST /v1/requestsrequiredsubmitted (see below)none — see Creating a request
PATCH /v1/requests/{id}partialunchangednone
POST /v1/requests/{id}/resubmitnoneunder_review, or submittedcapability_request.under_review / .submitted
POST /v1/requests/{id}/cancelnonecancelledcapability_request.cancelled
GET /v1/requests——none
GET /v1/requests/{id}——none
GET /v1/requests/eligibility/{product_code}——none

under_review, pending_clarification, processing, completed and declined are set by
PayMongo during review. There is no merchant-facing API call for them — you observe them through
the webhook (or by polling GET /v1/requests/{id}).

Full request and response schemas, with a kyb_data example per product, are in the API
reference: Create capability request.

Status lifecycle

flowchart LR
  A([POST /v1/requests]) --> B[submitted]
  B -->|PayMongo picks it up| C[under_review]
  C -->|needs info| D[pending_clarification]
  D -->|PATCH, then resubmit| C
  C -->|approved| E[processing]
  E --> F[completed]
  C -->|rejected| G[declined]

Entry point. Every request you create starts in submitted. Nothing is needed from you to get
it reviewed.

Terminal statuses. completed, declined and cancelled. A declined request can only be
reopened by PayMongo, which re-emits capability_request.submitted on the same request ID.

Cancelling. Allowed from submitted, under_review and pending_clarification — these paths
are left off the diagram to keep it readable. Cancel is rejected from processing, because the
capability is already being provisioned, and from all three terminal statuses.

Creating a request

curl -X POST https://api.paymongo.com/v1/requests \
  -u sk_live_xxxxxxxxxxxx: \
  -H 'Content-Type: application/json' \
  -d '{
    "request_type": "onboarding",
    "product_code": "prd_svc_paymongo_ewallet_maya",
    "requester_id": "org_xxxxxxxxxxxx",
    "kyb_data": {}
  }'
FieldRequiredDescription
request_typeyesaccount_update for prd_svc_paymongo_account_update, onboarding for every other product.
product_codeyesThe capability being requested. See Product codes.
requester_idyesWho is opening the request — your organization ID (org_…). A parent opening a request for a child sends the parent's organization ID. Recorded for PayMongo's review; not returned.
kyb_datanoApplication data. Its shape depends on product_code — see kyb_data by product.

Which account. The request is created for the account whose secret key made the call, or —
for a parent — for the child named in the Account-ID header. See
Requests on linked accounts.

One open request per product code. A second create while one is still submitted,
under_review or pending_clarification is rejected as a duplicate. account_update is checked
per field: a second request is rejected only if it touches a field or document already being
changed by an open request.

Status it is created in. submitted, with two exceptions decided on the spot:

  • a prd_svc_paymongo_account_update that only changes business_size and/or business_age is
    auto-approved and created completed;
  • a request whose registered business website is on PayMongo's prohibited list is created and
    immediately declined.
⚠️

Creation does not emit an event

A create is not a status change, so no capability_request.* event is published for it —
including capability_request.submitted. The response body already tells you the resulting
status; use that, not a webhook. The first event you will normally see is
capability_request.under_review.

The two on-the-spot outcomes above are the exception: the auto-approved account update emits
capability_request.completed, and the auto-declined request emits
capability_request.declined.

Check eligibility first

For payment methods, check first so you fail fast:

curl https://api.paymongo.com/v1/requests/eligibility/prd_svc_paymongo_ewallet_maya \
  -u sk_live_xxxxxxxxxxxx:
{
  "data": {
    "product_code": "prd_svc_paymongo_ewallet_maya",
    "eligible": false,
    "missing": [
      { "type": "field", "key": "business_website", "label": "Business website is required" },
      { "type": "document", "key": "dti_registration", "label": "DTI registration is required" }
    ]
  }
}

missing lists what the account still has to supply — the same set enforced when creating the
request. Each entry's type is one of:

typeWhat to do
fieldSend the field in kyb_data, under key.
documentAttach the document as a files_<key> part — dti_registration above is sent as files_dti_registration. See Attaching documents.
business_typeThe account's business type is missing, or not one this payment method accepts. Set it with an account update first.
account_activationThe account has not completed activation yet. Nothing else can be requested until it has.

kyb_data by product

kyb_data is a JSON object. The keys below are the ones the API understands; what is actually
required is checked per product when the request is created, and an unmet requirement returns
400 naming the missing fields.

Documents appear in kyb_data as files_<purpose> keys holding the ID of an uploaded file, or an
array of them. You do not upload files separately — send them with the request, as described in
Attaching documents, and the IDs are filled in for you.

E-wallets and card

prd_svc_paymongo_ewallet_gcash, prd_svc_paymongo_ewallet_grabpay,
prd_svc_paymongo_ewallet_maya, prd_svc_paymongo_ewallet_shopeepay and
prd_svc_paymongo_card_visa_mastercard.

The account is the source of truth, so kyb_data is normally {} or omitted — nothing already
on the account needs re-sending. Call eligibility first. If it reports
something missing, include it in this request: a missing field (for example business_website) in
kyb_data, a missing document as a files_<purpose> part. What you send fills the gap for the
eligibility check and is written to the account when the request is approved.

{
  "request_type": "onboarding",
  "product_code": "prd_svc_paymongo_ewallet_gcash",
  "requester_id": "org_xxxxxxxxxxxx",
  "kyb_data": {}
}

Account update

prd_svc_paymongo_account_update changes the business profile. kyb_data is a partial
payload: only the fields being changed, never the whole profile. You do not need to send the old
values — PayMongo records what each changed field held before.

{
  "request_type": "account_update",
  "product_code": "prd_svc_paymongo_account_update",
  "requester_id": "org_xxxxxxxxxxxx",
  "kyb_data": {
    "business_trade_name": "Acme Home",
    "change_reason": "Rebranding"
  }
}

Rules, all checked when the request is created:

  • change_reason is required, unless the payload only changes business_size and/or
    business_age — those are auto-approved.
  • A trade-name, legal-name or business-type change requires a passed liveness check.
  • A trade-name change requires an enabled wallet, and carries the signed request letter as
    files_signed_request_letter.
  • A legal-name change requires a registered business type. The type the request moves the
    account to counts, so business_type and business_legal_name can be sent together.
  • business_type can be changed only while the account is still individual. It is refused once
    the account holds a registered type. The request carries the documents the new type
    requires — see Business documents by business type.
  • tax_gross_remittances: "do_not_exceed_500k" requires ack_sd_requirement: true in the same
    payload.
FieldValues / format
change_reasonFree text.
business_trade_nameFree text.
business_legal_nameFree text.
business_typesole_proprietor, partnership, corporation.
is_one_person_corporationtrue with business_type: corporation for a One Person Corporation.
business_descriptionFree text.
business_industryMerchant Category Code — see Merchant Category Codes.
business_sizeless_than_10, between_10_and_50, between_51_and_250, greater_than_250.
business_ageless_than_1_year, between_1_and_2_years, between_2_and_5_years, greater_than_5_years.
business_estimated_monthly_volumeless_than_100K, between_100K_and_300K, between_300K_and_500K, between_500K_and_1M, between_1M_and_3M, greater_than_3M.
business_websiteURL.
business_tinFor example 123-456-789-000.
business_has_physical_storesBoolean.
business_addressObject: line1, line2, city, state, postal_code, country (ISO 3166-1 alpha-2).
customer_service_numberPhone number, for example +639171234567.
support_emailEmail address.
pluginBoolean.
tax_gross_remittancesdo_not_exceed_500k, exceed_500k.
ack_sd_requirementBoolean.

Tax document

prd_svc_paymongo_tax_document takes documents only: files_bir_2303, files_tax_exemption and
files_tax_sworn_declaration, attached as parts of a multipart/form-data body. kyb_data can be
{}.

Attaching documents

Send the request as multipart/form-data instead of JSON:

  • one part named payload, with Content-Type: application/json, carrying exactly the JSON body
    you would otherwise send;
  • one part per document, named files_<purpose>. Repeat a part name to attach several documents
    of the same purpose.
curl -X POST https://api.paymongo.com/v1/requests \
  -u sk_live_xxxxxxxxxxxx: \
  -F 'payload={"request_type":"onboarding","product_code":"prd_svc_paymongo_tax_document","requester_id":"org_xxxxxxxxxxxx","kyb_data":{}};type=application/json' \
  -F '[email protected]'

The uploaded files are added to kyb_data under their part name before anything is validated, so
the request is checked exactly as if the documents had been there all along. A request with no
documents can be sent as plain application/json.

The same format works on PATCH /v1/requests/{id}. There, uploads are added to whatever that
key already holds — attaching a second document does not drop the first.

Uploaded documents are held with the request and only added to the account when PayMongo approves
it. Cancelling the request deletes them, and so does a create or update that fails validation.

LimitValue
Per file10 MB
Per request20 files, 50 MB in total
File typespdf, jpg, jpeg, png, doc, docx, heic, heif

Anything outside these limits is rejected with 400 before anything is stored.

Business documents by business type

What a business must provide depends on its type. This applies whenever documents are asked for:
a business_type change on an account update carries the documents for the new type, and a
payment method request fills in whichever ones eligibility reports missing.

Business typeRequiredOptional
individualnonefiles_bir_certificate_of_registration, files_sworn_declaration
sole_proprietorfiles_bir_certificate_of_registration, files_dti_registration (DTI Business Name Registration)files_sworn_declaration
partnershipfiles_bir_certificate_of_registration, files_sec_registration (SEC Certificate of Partnership), files_articles_of_partnerships, files_partnership_resolution (notarized)files_sworn_declaration
corporationfiles_bir_certificate_of_registration, files_sec_registration (SEC Certificate of Incorporation), files_articles_of_incorporation, files_by_laws (notarized), files_latest_gis (latest General Information Sheet), files_sec_certificate (notarized Secretary's Certificate)files_sworn_declaration
One Person Corporation (business_type: corporation + is_one_person_corporation: true)files_bir_certificate_of_registration, files_sec_registration (SEC Certificate of Incorporation), files_articles_of_incorporation, files_appointment_of_officers (OPC Form of Appointment of Officers), files_sec_certificate (notarized Secretary's Certificate)files_sworn_declaration

For a payment method, eligibility is the authoritative list of what the
account is still missing. A reviewer may ask for more through pending_clarification.

Document purposes

Any files_<purpose> name is accepted, and new purposes are added over time without a new API
version. files_draft is reserved and rejected. The purposes in use today:

Business documents

Part nameDocument
files_bir_certificate_of_registrationBIR Certificate of Registration
files_sworn_declarationNotarized Sworn Declaration
files_sec_registrationSEC Certificate of Incorporation / Partnership
files_by_lawsNotarized By-Laws
files_articles_of_incorporationArticles of Incorporation
files_latest_gisLatest General Information Sheet (GIS)
files_sec_certificateNotarized Secretary's Certificate
files_appointment_of_officersForm of Appointment of Officers (OPC)
files_articles_of_partnershipsArticles of Partnership
files_partnership_resolutionNotarized Partnership Resolution
files_dti_registrationDTI Business Name Registration certificate

Enhanced due diligence

Part nameDocument
files_amlc_questionnaireAMLC Questionnaire
files_amlc_certificate_of_registrationAMLC Certificate of Registration
files_mtppMTPP
files_bsp_certificate_of_registrationBSP Certificate of Registration
files_pagcor_licensePAGCOR License
files_ic_licenseIC License (Insurance Commission)
files_gcash_pcnc(GCash) PCNC
files_gcash_kyc_form(GCash) KYC Form
files_gcash_due_diligence_form(GCash) Due Diligence Form
files_paymongo_edd_formPayMongo EDD Form
files_rco_endorsementRCO Endorsement
files_enhance_due_diligenceEnhanced Due Diligence

Tax — tax document requests only

Part nameDocument
files_bir_2303BIR Form 2303 (Certificate of Registration)
files_tax_exemptionTax exemption certificate
files_tax_sworn_declarationTax sworn declaration

Others

Part nameDocument
files_signed_request_letterSigned request letter (trade-name change)
files_alien_cert_registrationAlien Certificate of Registration (ACR)
files_fda_cert_registrationFDA Certificate of Registration
files_kyc_transaction_proofTransaction screenshots
files_latest_mayor_permitLatest Mayor's Permit
files_partnership_agreementsPartnership / supplier agreements
files_board_resolutionBoard Resolution
files_signed_dsaSigned DSA
files_special_power_of_attySpecial Power of Attorney (SPA)
files_othersOthers
files_certificate_of_registration_from_dhsud_hoaCertificate of Registration from DHSUD – HOA
files_dot_accreditation_or_proof_of_membershipDOT Accreditation or Proof of Membership
files_screenshotsScreenshots
files_termsheetTerm sheet
files_internal_approvalsInternal Approvals
files_signed_moaSigned MOA
files_loan_depositsLoan Deposits
files_person_file_recordPerson File Record

Correcting a request

When PayMongo needs more, the request moves to pending_clarification and you receive a
capability_request.pending_clarification event. data.merchant_note says what is needed. Answering
takes two calls:

  1. PATCH /v1/requests/{id} with the corrected kyb_data and any requested documents. The patch
    shallow-merges into the stored kyb_data — top-level keys you send replace or add, every other
    key is left alone — and is validated the same way as a create. It never changes the status.
  2. POST /v1/requests/{id}/resubmit, with no body, to hand the request back for review. It
    returns to under_review, or to submitted if it has to wait to be picked up again.
curl -X PATCH https://api.paymongo.com/v1/requests/req_xxxxxxxxxxxx \
  -u sk_live_xxxxxxxxxxxx: \
  -H 'Content-Type: application/json' \
  -d '{ "kyb_data": { "business_trade_name": "Acme Home" } }'

curl -X POST https://api.paymongo.com/v1/requests/req_xxxxxxxxxxxx/resubmit \
  -u sk_live_xxxxxxxxxxxx:
⚠️

PATCH alone leaves the request waiting

A request in pending_clarification stays there, corrections stored, until you call resubmit.
Nobody reviews it in the meantime.

To withdraw a request, POST /v1/requests/{id}/cancel (no body). Uploaded documents PayMongo has
not approved yet are deleted with it.

Product codes

Product codeCapabilityrequest_type
prd_svc_paymongo_ewallet_gcashGCash payment methodonboarding
prd_svc_paymongo_ewallet_mayaMaya payment methodonboarding
prd_svc_paymongo_ewallet_grabpayGrabPay payment methodonboarding
prd_svc_paymongo_ewallet_shopeepayShopeePay payment methodonboarding
prd_svc_paymongo_card_visa_mastercardVisa / Mastercard card acceptanceonboarding
prd_svc_paymongo_tax_documentTax document filingonboarding
prd_svc_paymongo_account_updateBusiness profile updateaccount_update

Account activation (prd_svc_paymongo_account_activation) and the standard wallet
(prd_svc_paymongo_std_wallet) also appear as capability requests on an account, but PayMongo
opens them as part of activating the account — you do not request them over this API.

For parent platforms

A parent uses these endpoints for its own capabilities and for its
fully managed children's. Without an Account-ID
header, a request is scoped to the parent's own account. With one, it is scoped to the child named
in the header.

What a parent can do

GoalHow
Activate a payment method on the parent accountPOST /v1/requests with the parent's secret key, as above.
Update the parent's business profilePOST /v1/requests with product_code: prd_svc_paymongo_account_update.
Give a child its default capabilitiesActivate the child — see Quick start. Defaults are provisioned at activation.
Apply the same defaults to every new childAuto-configuration.
Request an extra capability or a profile change on a fully managed childPOST /v1/requests with the parent's secret key and Account-ID: org_{child_id} — see Requests on linked accounts.
Transact on an activated childAccount-ID header — see Linked transactions.

Requests on linked accounts

📘

Fully managed children only

A parent can open capability requests only on a child it fully manages — see
Fully managed accounts. On any other linked child,
the call returns 403 with accountid_operation_not_granted; that child requests its own
capabilities.

To open, read, correct, or cancel a request on a child, authenticate with the parent's secret
key and name the child in the Account-ID header — the same pattern as
Linked transactions. Every endpoint in
Endpoints accepts it. Send the parent's organization ID as requester_id.

curl -X POST https://api.paymongo.com/v1/requests \
  -u sk_live_parentxxxxxxxx: \
  -H 'Account-ID: org_childxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
    "request_type": "account_update",
    "product_code": "prd_svc_paymongo_account_update",
    "requester_id": "org_parentxxxxxxxx",
    "kyb_data": {
      "business_trade_name": "Acme Home",
      "change_reason": "Rebranding"
    }
  }'
  • The request belongs to the child. Its account_id is the child's, and the rules on this
    page — eligibility, kyb_data, documents, one open request per product code — are checked
    against the child's account.
  • Events go to the child's webhook, not the parent's. Every capability_request.* event for
    the request is delivered to the webhook registered on the child. Register one on each child with
    the same Account-ID header — see
    Linked transactions and
    Capability request webhooks.

Recommended parent flow

  1. Check eligibility — GET /v1/requests/eligibility/{product_code} before you show the
    capability as available in your own UI.
  2. Create the request — POST /v1/requests. Store the returned req_ ID against your own
    record, and read the returned status: it comes back submitted (or already completed /
    declined for the on-the-spot outcomes).
  3. Listen, do not poll — subscribe to capability_request.* on the webhook of the account the
    request belongs to (the child's, for a request on a child), and key your handler on
    data.attributes.data.id. See
    Capability request webhooks.
  4. Handle pending_clarification — read merchant_note.note, merchant_note.requested_fields
    and merchant_note.requested_files, collect what is asked for, PATCH the request, then
    POST .../resubmit. See Correcting a request.
  5. Settle on completed or declined — both are terminal. A declined request can only be
    reopened by PayMongo, which re-emits capability_request.submitted.

Related pages


Did this page help you?