[API] Create Contract
The Create Contract API creates a retention contract between your organization, as the lender, and a borrower organization. The overview explains the contract lifecycle.
¶ Use case
When you lend money to a supplier organization, create a contract so that Uber collects the repayments from that organization’s earnings. The borrower accepts or rejects the contract in Supplier Portal, and retention starts at startsAt.
¶ Supported supplier types
Financiers
¶ Scopes
vehicle_suppliers.financing.contracts
¶ Required permissions
The user that the access token represents needs supplier.contracts.write on the organization in lender.lenderId. See Access.
¶ Resource
/v1/vehicle-supplier/financing/contracts
¶ HTTP method
POST
¶ Authorization
¶ Example request
curl -X POST "https://api.uber.com/v1/vehicle-supplier/financing/contracts" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-d '{
"idempotencyKey": {
"value": "<uuid>"
},
"type": "CONTRACT_TYPE_B2B",
"lender": {
"lenderId": {
"value": "<lender_org_id>"
}
},
"borrower": {
"borrowerId": {
"value": "<borrower_org_id>"
}
},
"loanAmount": {
"amountE5": 1500000000,
"currencyCode": "USD"
},
"retentionConfig": {
"cadence": "RETENTION_CADENCE_WEEKLY",
"retentionStrategyType": "RETENTION_STRATEGY_TYPE_STATIC",
"retentionAmount": {
"percentRate": 10,
"maxCadenceCap": {
"amountE5": 50000000,
"currencyCode": "USD"
}
}
},
"metadata": {
"name": "Fleet expansion loan",
"countryIso2": "US",
"interestRate": 8.5,
"acceptanceExpiryAt": {
"value": 1792022400000
}
},
"startsAt": {
"value": 1793577600000
},
"endsAt": {
"value": 1825027200000
}
}'
This example is for a 15,000.00 USD loan. Uber retains 10% of the borrower’s earnings each week, at most 500.00 USD a week, starting 2 November 2026 with an end date of 1 November 2027. The borrower has until 15 October 2026 to accept. All three times are 00:00 UTC.
¶ Request body parameters
| Name | Type | Required | Description |
|---|---|---|---|
idempotencyKey |
object | Yes | UUID object. A UUID you generate for this contract. Send the same value when you retry the request. |
type |
enum | Yes | Contract type enum. Must be CONTRACT_TYPE_B2B. |
lender |
object | Yes | Lender object. Your organization. |
borrower |
object | Yes | Borrower object. The organization repaying the loan. Must be different from the lender. |
loanAmount |
object | Yes | Amount object. The amount to be repaid. Greater than 0, in the currency of metadata.countryIso2, and within the range allowed for that country. |
retentionConfig |
object | Yes | Retention config object. How much Uber retains in each period, and how long a period is. |
metadata |
object | Yes | Contract metadata object |
startsAt |
object | Yes | Timestamp object. When retention starts. Can’t be in the past or more than 365 days from now. |
endsAt |
object | Yes | Timestamp object. When the contract ends if the loan isn’t repaid first. Must be after startsAt and no more than 5 × 365 days after it. |
Every field inside idempotencyKey, lender, borrower, loanAmount, startsAt and endsAt is required.
¶ Retention config
| Name | Type | Required | Description |
|---|---|---|---|
cadence |
enum | Yes | Retention cadence enum. RETENTION_CADENCE_WEEKLY or RETENTION_CADENCE_MONTHLY. |
retentionStrategyType |
enum | Yes | Retention strategy type enum. Must be RETENTION_STRATEGY_TYPE_STATIC. |
retentionAmount |
object | Yes | Retention amount object. How much Uber retains in each period. |
¶ Retention amount
Send percentRate, maxCadenceCap, or both. Retention explains how they combine.
| Name | Type | Required | Description |
|---|---|---|---|
percentRate |
number | Conditional | Percentage of the borrower’s earnings to retain in each period, for example 10 for 10%. Greater than 0 and at most 100, with up to 2 decimal places. |
maxCadenceCap |
object | Conditional | Amount object. The most Uber retains in one period. Greater than 0, in the loan currency, and within the range allowed for the country and cadence. Both of its fields are required. |
¶ Contract metadata
| Name | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Your label for the contract. Not blank, and at most 128 characters. |
countryIso2 |
string | Yes | ISO 3166-1 alpha-2 country code, for example US. The loan must be in this country’s currency, and Uber retains only from earnings in this country. |
interestRate |
number | No | Annual interest rate in percent, for your records, for example 8.5. From 0 to 100, with up to 2 decimal places. Uber doesn’t use it to calculate retention. |
acceptanceExpiryAt |
object | Yes | Timestamp object. The borrower has to accept the contract before this time. Must be in the future and before startsAt. |
Uber ignores financierName on requests.
Financing contracts are available in selected countries. Ask your Uber POC which countries you can use and which loan and cap ranges apply.
¶ Example response
200 OK
{
"contractId": {
"value": "<contract_id>"
}
}
¶ Response body parameters
| Name | Type | Description |
|---|---|---|
contractId |
object | UUID object. The new contract’s ID. Use it with the other contract endpoints. |
¶ Rate limit
5 requests per hour for each developer application.
¶ Endpoint-specific errors
| HTTP status | Code | Cause |
|---|---|---|
400 |
invalid-argument |
A required field is missing or malformed; type, cadence or retentionStrategyType isn’t a supported value; retentionAmount sets neither value; percentRate or interestRate is out of range; name is blank or longer than 128 characters; or acceptanceExpiryAt isn’t in the future. |
400 |
invalid-amount |
loanAmount or maxCadenceCap is 0 or less, or outside the range allowed for the country. |
400 |
invalid-currency |
loanAmount isn’t in the country’s currency, or maxCadenceCap isn’t in the loan currency. |
400 |
invalid-effective-start-date |
startsAt is in the past or more than 365 days away, or acceptanceExpiryAt isn’t before startsAt. |
400 |
invalid-effective-end-date |
endsAt isn’t after startsAt, or it’s more than 5 × 365 days after startsAt. |
400 |
invalid-entity |
lenderId and borrowerId are the same. |
400 |
unknown-country-code |
Financing contracts aren’t available in countryIso2, or it isn’t a known country. |
400 |
org-not-found |
The lender or borrower organization doesn’t exist. |
400 |
contract-already-exists |
You already created a contract with this idempotencyKey. |
400 |
rate-limited |
The borrower already has the maximum number of pending or active contracts in this country. retryable is true because the request can succeed after one of those contracts ends. |
401 |
permission-denied |
The token’s user doesn’t have supplier.contracts.write on the lender organization. A missing or malformed lender.lenderId also returns this error. See Access. |
500 |
internal-server-error |
Retry with the same idempotencyKey. |
¶ Notes
- New contracts wait in
CONTRACT_STATE_PENDING_ACCEPTANCEfor the borrower. If the borrower doesn’t accept beforeacceptanceExpiryAt, Uber terminates the contract with reasonCONTRACT_STATE_REASON_ACCEPTANCE_WINDOW_EXPIRED. - If Uber has set up automatic acceptance between your organization and the borrower, the contract is accepted without the borrower’s review.
- Get Contract and Search Contracts may not return the new contract until a few seconds after this call.
- If a request fails or times out, retry it with the same
idempotencyKey. If the first attempt created the contract, the retry fails withcontract-already-existsand no second contract is created. Use Search Contracts to find the existing one. Uber validates each retry again, so a late retry can fail validation instead, for example becausestartsAthas passed. interestRateis for your records. Uber doesn’t add interest toloanAmount.