UAE Rent Now Pay Later: Partner API flow

This guide walks through a UAE Rent Now Pay Later (RNPL) application on the Rently Partner API (public v2): which endpoint to call at each step, what to send and what comes back.

The full request and response schemas are in the Partner API reference.

Before you start

Every request needs an access token from POST /v2/Token, sent as Authorization: <tokenType> <accessToken>. Getting the token is covered in Get Started.

The flow at a glance

Each box is a status returned by GET /v2/ae/rnpl/{productFlowId}, coloured by who acts next: the partner, Rently or the tenant. Arrows show what moves the application on; the partner's arrows are the endpoints to call.

Loading diagram…

Blue: the partner acts. Purple: Rently acts. Yellow: the tenant acts, on the Rently website. Green: done. Red: stopped. Dashed: optional.

GET /v2/ae/rnpl/{productFlowId} can be called in any status to see where the application is.

StatusWho actsWhat to do
Before the application existsPartnerOptionally price it with POST /v2/ae/rnpl/quote (step 1), then create it with POST /v2/ae/rnpl (step 2).
idlePartnerUpload the documents with POST /v2/blob/upload (step 3), attach them with PUT /v2/ae/rnpl/{productFlowId} (step 4) and submit with POST /v2/ae/rnpl/{productFlowId}/advance (step 5).
pendingRentlySubmitted. Rently's team reviews it and approves it, rejects it or asks for more documents. Nothing to call.
document-requiredPartnerRently's team asked for more documents; the reason is in review.documentRequiredReason. Upload the documents with POST /v2/blob/upload (step 3) and attach them with PUT /v2/ae/rnpl/{productFlowId} (step 4). The application goes back to pending.
approvedRentlyApproved. Rently prepares the agreement and moves the application to signing. Nothing to call.
signingTenantThe tenant continues the journey on Rently by clicking continueUrl (step 7).
completedDoneThe tenant finished the journey on Rently.
rejectedStoppedRejected by Rently's team; the reason is in review.rejectReason. Final.

Also available at any point:

EndpointPurpose
GET /v2/ae/rnpl/applications/{userId}List a tenant's applications.
GET /v2/ae/rnpl/{productFlowId}/schedulesPreview the application's payment schedule. Nothing is saved.
GET /v2/blob/downloadDownload a file uploaded earlier.

1. Quote the application (optional)

POST /v2/ae/rnpl/quote prices an application before it exists. It takes the same payload as the create endpoint (step 2), minus intendedPaymentMethod, and validates it the same way, so it is also a safe way to check the payload. Nothing is saved.

{
  "totalPayment": 8420.5,
  "currency": "AED",
  "items": [
    { "label": "Monthly principal", "amount": 8000, "rate": null },
    { "label": "Subscription Fee", "amount": 420.5, "rate": 5.25 }
  ]
}

totalPayment is the monthly installment the tenant would pay: the monthly principal plus the subscription fee. items lists each line of the quote, such as the rent financed, the deposit, the monthly principal and the subscription fee. The values above are illustrative.

2. Create the application

POST /v2/ae/rnpl starts an application on behalf of your tenant.

{
  "userId": null,
  "currency": "AED",
  "partnerReferenceId": "HT-2026-000123",
  "lease": {
    "leaseType": "found-place",
    "annualRent": 96000,
    "numberOfCheques": 4,
    "leaseDurationInMonths": 12,
    "moveInDate": "2026-11-01",
    "deposit": { "amount": 5000 }
  },
  "property": {
    "location": "dubai",
    "address": "Apartment 1204, Marina Gate 2, Dubai Marina"
  },
  "tenant": {
    "fullName": "Aisha Rahman",
    "email": "tenant@example.com",
    "phoneNumber": "+971501234567",
    "identityNumber": "784-1990-1234567-1",
    "monthlyIncome": 15000,
    "hasCoapplicant": false
  },
  "landlord": {
    "fullName": "Omar Haddad",
    "email": "landlord@example.com",
    "phoneNumber": "+971507654321",
    "bankAccount": { "bankCode": "HBZUAEAD", "iban": "AE070331234567890123456" }
  },
  "intendedPaymentMethod": "Card"
}
{
  "productFlowId": "<application id>",
  "userId": "<tenant's user id>"
}

Store both ids on your side:

  • productFlowId identifies the application in every later call.
  • userId identifies the tenant. Leave userId out (or null) for a new tenant and Rently generates one. Send it on the tenant's later applications so they are grouped under the same user, and use it to list them with GET /v2/ae/rnpl/applications/{userId}.

Field rules

FieldRule
currencyOptional. Defaults to AED, the only accepted value. All amounts are in AED.
partnerReferenceIdOptional. Your own reference, e.g. your application or lease id. Rently stores it with the application.
lease.leaseTypefound-place, renewing, mid-lease-switch or not-yet-secured.
lease.numberOfCheques1, 2, 3, 4 or 6.
lease.leaseDurationInMonthsBetween 6 and 12.
lease.moveInDateYYYY-MM-DD. All dates use this format.
lease.depositOptional. Ignored for mid-lease-switch.
lease.midLease{ chequesRemaining, rentRemaining }. Required when leaseType is mid-lease-switch.
property.locationdubai, abu-dhabi, sharjah, ajman or ras-al-khaimah.
tenant.identityNumberThe tenant's Emirates ID number.
tenant.monthlyIncomeBetween 7,000 and 999,999.
tenant.hasCoapplicantWhether the tenant splits the rent with someone.
landlord.bankAccount.bankCodeSWIFT (BIC) code of a UAE bank, 8 or 11 characters.
landlord.bankAccount.ibanUAE IBAN without spaces: AE followed by 21 digits.
intendedPaymentMethodCard or DirectDebit.

3. Upload the documents

Each document is uploaded first with POST /v2/blob/upload, then attached to the application in step 4.

Send the request as multipart/form-data with two fields:

  • blobType: 11 (product flow files).
  • files: one or more files. Up to 10 files per request, and the whole request must be 10 MB or smaller.
{
  "blobNames": ["productflowfiles/3f2c9a1e-emirates-id-front.pdf"]
}

blobNames lists the stored path of each file, in the order they were sent. Files are always renamed, so keep these paths: they are what you attach in step 4 and what you download with GET /v2/blob/download?blobType=11&blobName=<path>.

4. Attach the documents

PUT /v2/ae/rnpl/{productFlowId} sets the application's documents. For each file, send the path returned by the upload as url (the path, not a full URL) together with the file's metadata.

{
  "attachments": {
    "emiratesId": [
      {
        "url": "productflowfiles/3f2c9a1e-emirates-id-front.pdf",
        "fileName": "emirates-id-front.pdf",
        "contentType": "application/pdf",
        "size": 254812
      }
    ],
    "fullCreditReport": [ { "url": "...", "fileName": "...", "contentType": "...", "size": 0 } ],
    "ejari": [ { "url": "...", "fileName": "...", "contentType": "...", "size": 0 } ],
    "salaryCertificate": [],
    "bankStatements": [],
    "otherDocuments": []
  }
}
AttachmentRequiredFiles
emiratesIdYes1 to 2 (front and back)
fullCreditReportYesExactly 1 (AECB full credit report)
ejariYesExactly 1 (registered Ejari tenancy contract)
salaryCertificateNoUp to 2 (issued less than 30 days ago)
bankStatementsNoUp to 6 (last three bank statements)
otherDocumentsNoUp to 5

Accepted files are application/pdf, image/png and image/jpeg, 10 MB each at most.

The update replaces the application's documents. Files left out of the request are removed, and files already attached (same url under the same document) stay as they are. To add a file, send the files the application already has (from attachments in GET /v2/ae/rnpl/{productFlowId}) together with the new one.

You can call this endpoint as often as needed while the application accepts documents (see The flow at a glance).

5. Advance the application

POST /v2/ae/rnpl/{productFlowId}/advance moves the application to its next status, e.g. submits it for review once its documents are in. It has no request body: whatever the next status needs must already be on the application, sent through the create and update endpoints.

When something is missing, the application stays where it is and errors says what.

6. Follow the application

GET /v2/ae/rnpl/{productFlowId} returns the application in the shape it was created with, plus:

FieldMeaning
idThe application id.
statusWhere the application is. See The flow at a glance.
review.documentRequiredReasonWhat the tenant still needs to provide. Set when Rently moves the application to document-required.
review.rejectReasonWhy the application was rejected. Set when Rently moves it to rejected.
continueUrlLink where the tenant continues their application on Rently.
attachmentsThe documents attached in step 4. null until they are provided.

Read the application again to see when its status changes, or register a webhook to be notified with an ApplicationStatusChangeEvent.

7. Send the tenant to Rently

When the status is signing, give the tenant continueUrl, e.g. as a link or button. The tenant continues the journey on Rently by clicking it and signs the agreement there. Once they finish, the application moves to completed.

List a tenant's applications

GET /v2/ae/rnpl/applications/{userId} returns the ids of the applications a tenant made through you. Read each one with GET /v2/ae/rnpl/{productFlowId}. An unknown userId returns an empty list.

{
  "userId": "<tenant's user id>",
  "productFlowIds": ["<application id>", "<application id>"]
}

Preview the payment schedule

GET /v2/ae/rnpl/{productFlowId}/schedules returns every payment the application would schedule, in the order they fall due. Nothing is saved, and the schedule is built from what the application carries now; when something it needs is missing, schedules is empty and errors says what.

{
  "productFlowId": "<application id>",
  "schedules": [
    {
      "party": "tenant",
      "type": "money-in",
      "description": "Monthly installment",
      "amount": 8420.5,
      "discountAmount": 0,
      "finalAmount": 8420.5,
      "currency": "AED",
      "paymentDate": "2026-11-01"
    }
  ]
}
FieldValues
partyWho the payment is with: tenant, landlord or b2b-entity.
typemoney-in (collected from the tenant), money-out (paid out to the landlord) or on-behalf (paid on a party's behalf).
finalAmountWhat is actually collected or paid: amount less discountAmount.

Errors

A call can fail in two ways, so check both:

  1. A non-2xx status. 401 means the token is missing, expired or invalid. Request validation failures return 400 with the fields at fault:
 {
   "title": "One or more validation errors occurred.",
   "errors": { "lease.numberOfCheques": ["..."] }
 }
  1. A 200 with errors. Every response body can carry an errors array. When it is not empty, the call did not succeed:
 {
   "errors": [{ "code": "PSAE015", "message": "The application cannot be found." }]
 }
CodeEndpointMeaning
PSAE012POST /v2/blob/uploadThe file upload failed. Try again.
PSAE013GET /v2/blob/downloadThe requested file cannot be found.
PSAE014POST /v2/ae/rnplThe application could not be created. Try again.
PSAE015Application endpointsThe application cannot be found.
PSAE016Application endpointsThe application could not be retrieved. Try again.
PSAE017PUT /v2/ae/rnpl/{productFlowId}The application could not be updated. Try again.
PSAE018POST /v2/ae/rnpl/{productFlowId}/advanceThe application could not be advanced. Try again.
PSAE019POST /v2/ae/rnpl/quoteThe quote could not be calculated. Try again.
PSAE020GET /v2/ae/rnpl/{productFlowId}/schedulesThe payment schedule could not be retrieved. Try again.
SEC003Application endpointsThe application belongs to another partner.