OuiPay
API ReferenceServices

Validate a recipient

POST /v1/services/{serviceCode}/validate : verify a meter, smartcard, or account before quoting.

POST /v1/services/{serviceCode}/validate

Verifies the recipient identifier against the fulfilment rail before money moves: meter number for electricity/water, smartcard for tv, customer ID for internet, candidate ID for education. Call it whenever the definition marks a step requires_validation, and pass the response back as validation_snapshot on the order.

Headers

HeaderRequiredValue
AuthorizationyesBearer sk_...
Content-Typeyesapplication/json

Body

FieldTypeRequiredNotes
country_codestringyesService country
account_refstringyesThe recipient identifier being verified
operator_codestringnoSelected operator (required by most rails)
product_codestringnoSelected plan, when the rail needs it
meter_typestringnoSelected variant (e.g. prepaid)
phonestringnoContact phone when the rail asks for it

Request

curl https://api.ouipay.africa/v1/services/electricity/validate \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "country_code": "NG",
    "account_ref": "04591234567",
    "operator_code": "ikeja-electric",
    "meter_type": "prepaid"
  }'

Response 200

{
  "data": {
    "service_code": "electricity",
    "country_code": "NG",
    "account_ref": "04591234567",
    "valid": true,
    "customer_name": "A. OKONKWO",
    "address": "12 ADEOLA ST, IKEJA",
    "serviceability": { "serviceable": true, "reason": null }
  }
}
FieldTypeNotes
validbooleanThe identifier resolved on the rail
customer_namestringRegistered name when the rail returns one
serviceabilityobjectserviceable: a rail can actually fulfil this recipient
phone_validationobjectairtime/data only: normalized number, type, carrier

valid and serviceability.serviceable are different checks: a structurally valid meter number can still be unserviceable in a country with no fulfilment binding. Require both before quoting.

For airtime and data, phone_validation carries the platform-level result (valid, normalized E.164, country_code, number_type, carrier, messages) ahead of the rail check: impossible numbers and country/number mismatches fail here without reaching the rail. When normalized is present, the rail check already ran against it: reuse that value on the order.

Errors

HTTPerror.codeCause
422VALIDATION_ERRORMissing account_ref/country_code, or the rail rejected the lookup
403SERVICE_COUNTRY_NOT_ELIGIBLECountry not eligible for this account
422SERVICE_UNAVAILABLEService not offered in the requested country