diff --git a/_transactions.md b/_transactions.md
index 61e042b..2e3ae93 100644
--- a/_transactions.md
+++ b/_transactions.md
@@ -100,7 +100,7 @@ curl https://api.uphold.com/v0/me/cards/a6d35fcd-xxxx-9c9d1dda6d57/transactions
}
```
-> When the Travel Rule applies to the transaction, the response also includes:
+> When the Travel Rule applies to a transaction created without `?commit=true`, the response also includes:
```json
{
@@ -131,21 +131,25 @@ The first step is to prepare the transaction by specifying:
- The _currency_ to denominate the transaction by.
- The _amount_ of value to send in the denominated currency.
+- An optional denomination _target_ (`origin` or `destination`), determining which side of the transaction the denominated amount applies to:
+ when set to `destination`, fees are added on top of the denominated amount, so that the destination receives that exact amount;
+ when set to `origin`, fees are deducted from it instead.
+ By default, the target is the `destination` when converting to a different currency while denominating in the destination currency, and the `origin` otherwise.
- The _origin_ of the transaction, which can be an account id in the case of a _deposit_.
- The _destination_ of the transaction, which can be in the form of a [crypto network address](#create-card-address), an email address, an account id, an application id, or a [card id](#card-object).
- An optional _message_, which is shown to the user to provide additional context.
- An optional _reference_ code, which can be used as a unique identifier of the transaction in an external system, or for similar purposes.
- An optional _priority_ for the transaction ("normal" or "fast", with the default being "normal"),
to signal the intent to fast-track its completion in exchange for a higher fee.
- This is currently only supported for the Dash network.
+ Notably, this enables instant withdrawals to US bank accounts via ACH; for withdrawals on the Dash network, it results in a higher network fee.
The following table describes the types of transactions currently supported:
-Type | Origin | Destination
----------- | ----------------------------------- | --------------------------------------------------------
-deposit | ACH, credit card or SEPA account id | Uphold card id
-withdrawal | Uphold card id | ACH or SEPA account id, or cryptocurrency address
-transfer | Uphold card id | Email address, Application id or Uphold card id
+Type | Origin | Destination
+---------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+deposit | Bank account id (ACH, FPS or SEPA; SWIFT or WIRE for unlinked accounts) or credit card account id | Uphold card id
+withdrawal | Uphold card id | Bank account id (ACH, FPS or SEPA; SWIFT or WIRE for unlinked accounts), credit/debit card account id, alternative payment method (e.g. Interac or Apple Pay), or cryptocurrency address
+transfer | Uphold card id | Email address, Application id or Uphold card id
Upon preparing a transaction, a [Transaction Object](#transaction-object) will be returned with a newly-generated `id`, and a status of `pending`.
@@ -156,7 +160,8 @@ Upon preparing a transaction, a [Transaction Object](#transaction-object) will b
Adding the query string parameter ?commit=true to this request will create and commit the transaction in a single step.
- If the deposit origin is a CARD account ID and the query string parameter ?commit=true is set, you need to send the credit card's securityCode in the request body.
+ If the deposit origin is a CARD account ID and the query string parameter ?commit=true is set, the credit card's securityCode may be required in the request body.
+ This API accepts it as an optional field, but the card gateway may still require it to process the deposit.
Important Notice : In compliance with PCI standards, the Uphold Sandbox environment does not accept real credit/debit card data. For a list of accepted card data, please refer to the Adding credit/debit card accounts section of the documentation.
@@ -167,39 +172,41 @@ Upon preparing a transaction, a [Transaction Object](#transaction-object) will b
`POST https://api.uphold.com/v0/me/cards/:card/transactions`
- Requires any of the following scopes: transactions:deposit, transactions:transfer:application, transactions:transfer:others, transactions:transfer:self or transactions:withdraw for Uphold Connect applications.
+ Requires any of the following scopes: transactions:transfer:application, transactions:transfer:others, transactions:transfer:self, transactions:withdraw or transactions:write for Uphold Connect applications.
If creating with the query string parameter ?commit=true, the scope has to match the type of transaction being committed.
+ Deposits additionally require the transactions:deposit scope, which is checked based on the type of transaction, after route authorization.
### Response
-Returns a [Transaction Object](#transaction-object).
+Returns a [Transaction Object](#transaction-object), with HTTP status code `202` when the transaction is created without the query string parameter `?commit=true`, or `200` when it is created and committed in a single step.
If the deposit origin is a CARD account ID and the query string parameter ?commit=true is set,
the transaction's params will include a redirect field with information of a redirect URI to be followed to complete the credit card deposit.
- If the withdrawal is subject to the Travel Rule, the response will include a requirements array and a requirementsDetails object containing the requestForInformationId.
+ If the withdrawal is subject to the Travel Rule and the transaction is created without the query string parameter ?commit=true, the response will include a requirements array and a requirementsDetails object with the isAddressVerified, isRequired and requestForInformationId fields, along with an optional reason explaining why the requirement applies.
The travel rule information must be submitted via the Submit Travel Rule Information endpoint before committing the transaction .
### Step 2: Commit Transaction
Once a transaction has been created and a quote secured, commit the transaction using the previously returned `id`.
-An optional parameter `message` can also be sent which will overwrite the value currently stored in the transaction.
+The optional parameters `beneficiary`, `message`, `purpose` and `reference` can also be sent, which will overwrite the values currently stored in the transaction.
Once the transaction is committed, its status will change to `processing`.
- This must be done within the time window specified (in miliseconds) by the params.ttl field of the transaction object.
+ This must be done within the time window specified (in milliseconds) by the params.ttl field of the transaction object.
Attempting to commit a transaction past this timeframe results in a 404 HTTP error .
If the transactions:commit:otp permission has been granted by the user, and an OTP is not provided with the request,
- you will get a 401 HTTP error , along with the HTTP header OTP-Token: Required.
+ you will get a 401 HTTP error , along with the HTTP header OTP-Token: required.
In that case, re-send the request, including the OTP verification code like so:
OTP-Token: <OTP-Token>.
+ Note that this OTP challenge can also occur at the create step, when using the query string parameter ?commit=true.
### Request
@@ -208,11 +215,13 @@ Once the transaction is committed, its status will change to `processing`.
Requires any of the following scopes, based on the type of transaction being committed:
- transactions:deposit, transactions:transfer:application, transactions:transfer:others, transactions:transfer:self or transactions:withdraw
+ transactions:transfer:application, transactions:transfer:others, transactions:transfer:self, transactions:withdraw or transactions:write
for Uphold Connect applications.
+ Deposits additionally require the transactions:deposit scope, which is checked based on the type of transaction, after route authorization.
- If the deposit origin is a CARD account ID, you need to send the credit card's securityCode in the request body.
+ If the deposit origin is a CARD account ID, the credit card's securityCode may be required in the request body.
+ This API accepts it as an optional field, but the card gateway may still require it to process the deposit.
If the user has recently changed their password, they may be in a cool-down period where outbound transactions are not allowed, for security reasons.
@@ -230,7 +239,7 @@ Returns a [Transaction Object](#transaction-object).
## Specify destination currency
-> Example of creating a EUR to BTC transaction denominated in USD (i.e. buying 10 USD worth of BTC with and EUR card), by using the address of a EUR card as the `origin` in the URL parameter, and the address of an BTC card in the `destination` field, in the body of the request:
+> Example of creating a EUR to BTC transaction denominated in USD (i.e. buying 10 USD worth of BTC with a EUR card), by using the address of a EUR card as the `origin` in the URL parameter, and the address of a BTC card in the `destination` field, in the body of the request:
```bash
curl https://api.uphold.com/v0/me/cards/a6d35fcd-xxxx-9c9d1dda6d57/transactions \
@@ -291,7 +300,7 @@ curl https://api.uphold.com/v0/me/cards/a6d35fcd-xxxx-9c9d1dda6d57/transactions
```
By using a [card](#card-object) id as the destination of a transaction, it is possible to determine the destination currency, independently from the denomination.
-For example, to convert 10 USD worth of EUR to BTC, one could create a transaction from an EUR card to a BTC card, and denominate it in USD. An example is shown to the side.
+For example, to convert 10 USD worth of EUR to BTC, one could create a transaction from a EUR card to a BTC card, and denominate it in USD. An example is shown to the side.
## Confirm a Credit Card Deposit
@@ -362,19 +371,14 @@ A webpage for 3DSecure confirmation for the user to interact with.
As the cryptocurrency market grows and starts interacting more and more with the traditional finance world new rules are applied to the FinTech sector.
As such, under the regulatory action of The Financial Action Task Force [FATF](https://www.fatf-gafi.org/), we are required to comply with the [travel rule](https://www.fatf-gafi.org/media/fatf/documents/recommendations/RBA-VA-VASPs.pdf) which requires us to "obtain, hold, and transmit required originator and beneficiary information in order to identify and report suspicious transactions, monitor the availability of information, take freezing actions, and prohibit transactions with designated persons and entities."
+For cryptocurrency withdrawals, the originator and beneficiary information is collected via the [Get Travel Rule Details](#get-travel-rule-details) and [Submit Travel Rule Information](#submit-travel-rule-information) endpoints.
+Independently of that process, the following complementary fields can be sent when [creating](#step-1-create-transaction) or [committing](#step-2-commit-transaction) a transaction:
+
> Example of a transaction creation payload including `beneficiary` and `purpose` fields:
```json
{
"beneficiary": {
- "address": {
- "city": "Ryleighfort",
- "country": "US",
- "line1": "32167 Mohr Land",
- "state": "US-CA",
- "zipCode": "47890"
- },
- "name": "Han Solo",
"relationship": "child"
},
"denomination": {
@@ -388,8 +392,8 @@ As such, under the regulatory action of The Financial Action Task Force [FATF](h
Parameter | Required | Description
----------- | -------- | -----------
-beneficiary | yes/no | The transaction beneficiary information. See [Beneficiary](#beneficiary). Required for transfers to other users and withdrawals above _$3000 USD_ (or _$1000 USD_, if the origin user is from Arizona, United States). Note: ACH withdrawals do not require the beneficiary information to be sent. We only support personal bank accounts therefore the beneficiary (ACH account holder) is assumed to be the Uphold user who added that account.
-purpose | yes/no | The reason for the transaction. Required for transactions in which the relationship is not set to `myself`. For business relationships, the possible values are: `business_expenses`, `business_travel`, `consultancy_expenses`, `education_expenses`, `family_expenses`, `funding_investments`, `gift_or_donations`, `invoice_payment`, `loan_payment`, `personal_expenses`, `salary_payments`, and `technology_expenses`. For personal relationships, the possible values are: `bill_payments`, `donations`, `expenses`, `gift`, `living_expenses`, `payment_for_goods_or_services`, and `supporting_family_internationally`.
+beneficiary | no | The transaction beneficiary information. See [Beneficiary](#beneficiary).
+purpose | no | The reason for the transaction. It is ignored when the beneficiary `relationship` is set to `myself`. For business relationships, the possible values are: `business_expenses`, `business_travel`, `consultancy_expenses`, `education_expenses`, `family_expenses`, `funding_investments`, `gift_or_donations`, `invoice_payment`, `loan_payment`, `personal_expenses`, `salary_payments`, `sale_of_nfts_or_return_of_credits`, and `technology_expenses`. For personal relationships, the possible values are: `bill_payments`, `donations`, `expenses`, `gift`, `living_expenses`, `payment_for_goods_or_services`, and `supporting_family_internationally`.
### Beneficiary
@@ -397,45 +401,28 @@ This beneficiary field has the following properties:
Parameter | Required | Description
------------ | ----------- | -----------
-address | yes/no | The transaction beneficiary address information. See [Address](#address). Required for external beneficiaries.
-name | yes/no | The beneficiary's full name. Required for external beneficiaries. For all transactions, except those with `relationship` type `business`, the name must be composed of at least, 2 words with a minimum of 2 characters each, for the first and last word.
-relationship | yes | Reflects the beneficiary's relationship to the transaction originator. Possible values are `business`, `child`, `co_worker`, `friend`, `myself`, `parent`, `sibling`.
-
-### Address
-
-Property | Required | Description
--------- |--------- | -----------
-city | yes | The beneficiary address city.
-country | yes | The beneficiary address country.
-line1 | yes | The beneficiary address line 1.
-line2 | no | The beneficiary address line 2.
-state | yes | The beneficiary address state.
-zipCode | yes | The beneficiary address zip code.
-
-### Beneficiary Requirements
-
-To obtain the transaction beneficiary requirements (or validate the `beneficiary` object) use the `?validate=true` query parameter when creating the quote. This will generate a validation error if any required beneficiary information is missing. Otherwise, the transaction will fail at the commit step with a similar error message.
+email | yes/no | The beneficiary's email address. Required for Interac withdrawals only.
+name | yes/no | The beneficiary's full name. Required for Interac withdrawals only; it is not stored for any other type of transaction.
+relationship | yes | Reflects the beneficiary's relationship to the transaction originator, as a free-form string of 1 to 255 characters. Common values are `business`, `child`, `co_worker`, `friend`, `myself`, `parent`, `sibling`.
- Please note that at this moment, even with the validate=true parameter, the validation is only performed if a beneficiary object is passed.
+ The beneficiary's name and address are not persisted with the transaction: only the relationship is kept. For Interac withdrawals, the email and name are kept instead.
+ ACH withdrawals always record the beneficiary with relationship set to myself: we only support personal bank accounts, therefore the beneficiary (ACH account holder) is assumed to be the Uphold user who added that account.
-> Example of including the beneficiary information when creating a quote, alongside the remaining transaction data:
+### Validating a Transaction
+
+To validate a transaction without committing it, use the `?validate=true` query string parameter when [creating](#step-1-create-transaction) it.
+This runs the generic quote validation, along with the scope and OTP checks that would otherwise be performed when committing the transaction, based on its type.
+
+> Example of validating a quote with beneficiary information, using the `?validate=true` query string parameter:
```bash
-curl 'https://api-sandbox.uphold.com/v0/me/cards//transactions' \
+curl 'https://api-sandbox.uphold.com/v0/me/cards//transactions?validate=true' \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
-d '{
"beneficiary": {
- "address": {
- "city": "Ryleighfort",
- "country": "US",
- "line1": "32167 Mohr Land",
- "state": "US-CA",
- "zipCode": "47890"
- },
- "name": "Han Solo",
"relationship": "child"
},
"denomination": {
@@ -456,66 +443,12 @@ curl 'https://api-sandbox.uphold.com/v0/me/cards//transactions/' \
-d '{
"beneficiary": {
- "address": {
- "city": "Ryleighfort",
- "country": "US",
- "line1": "32167 Mohr Land",
- "state": "US-CA",
- "zipCode": "47890"
- },
- "name": "Han Solo",
"relationship": "child"
},
"purpose": "donations"
}'
```
-> In both cases, incomplete beneficiary information will be reported in a format similar to this:
-
-```json
-{
- "code": "validation_failed",
- "errors": {
- "beneficiary": {
- "code": "validation_failed",
- "errors": {
- "name": [
- {
- "code": "required",
- "message": "This value is required"
- }
- ]
- }
- }
- }
-}
-```
-
-> Invalid beneficiary information will be reported like this:
-
-```json
-{
- "code": "validation_failed",
- "errors": {
- "beneficiary": {
- "code": "validation_failed",
- "errors": {
- "name": [
- {
- "code": "invalid_beneficiary",
- "message": "The provided beneficiary is invalid"
- }
- ]
- }
- }
- }
-}
-```
-
-
- For regulatory compliance reasons, the beneficiary name is checked by a sanctions screening process, and is expected to consist entirely of characters in the Latin, Cyrillic, Greek or Georgian alphabets, along with a limited set of special characters. These validations may result in an invalid_beneficiary error.
-
-
## List User Transactions
```bash
@@ -624,6 +557,14 @@ Requests a list of committed transactions associated with the current user.
This endpoint supports [Pagination](#pagination).
+You can filter the list of returned transactions using the `q` query string parameter. Supported filters are:
+
+- `createdAt:`, which accepts the comparison operators `>`, `>=`, `<` and `<=` (e.g. `createdAt:>=2024-01-01`), as well as date ranges (e.g. `createdAt:2024-01-01..2024-03-31`).
+- `origin.CardId:` and `destination.CardId:`, which accept a single card id or a comma-separated list of card ids.
+
+Multiple filters can be used together, separated with a space.
+The `origin.CardId:` and `destination.CardId:` filters can also be combined with the `OR` keyword, e.g. `origin.CardId:"" OR destination.CardId:""`.
+
### Response
Returns an array of [Transaction Objects](#transaction-object).
@@ -743,30 +684,27 @@ Returns an array of [Transaction Objects](#transaction-object).
## Get All Transactions (Public)
```bash
-curl -X GET "https://api.uphold.com/v0/reserve/transactions"
+curl -X GET "https://api.uphold.com/v0/reserve/transactions" \
+ -H "Authorization: Bearer "
```
> The above command returns the following JSON (truncated for brevity):
```json
[{
+ "application": null,
"createdAt": "2014-09-25T19:19:51.201Z",
"denomination": {
"amount": "25.00",
- "currency": "USD",
- "pair": "USDUSD",
- "rate": "1.00"
+ "currency": "USD"
},
"destination": {
- "CardId": "d42999c4-30c9-4a61-889c-62a4050bce88",
"amount": "0.02777777",
"base": "0.02777777",
"commission": "0.00",
"currency": "BTC",
- "description": "Nuno Sousa",
"fee": "0.00",
- "rate": "0.00111111",
- "type": "card"
+ "rate": "0.00111111"
},
"fees": [{
"amount": "0.00",
@@ -776,48 +714,34 @@ curl -X GET "https://api.uphold.com/v0/reserve/transactions"
"type": "exchange"
}],
"id": "63dc7ccb-0e57-400d-8ea7-7d903753801c",
- "message": null,
- "normalized": [{
- "amount": "22.94",
- "commission": "0.00",
- "currency": "EUR",
- "fee": "0.00",
- "rate": "0.91759"
- }],
"origin": {
- "CardId": "f4dbc023-61bb-43e9-9ce6-7f34efd9e688",
"amount": "25.00",
"base": "25.00",
"commission": "0.00",
"currency": "USD",
- "description": "Nuno Sousa",
"fee": "0.00",
"rate": "900.00000",
"sources": [{
"amount": "25.00",
"id": "4586e3f6-5fff-473f-b479-4e7ce2ba14cf"
- }],
- "type": "card"
+ }]
},
"params": {
"currency": "USD",
"margin": "0.00",
"pair": "BTCUSD",
- "progress": "1",
- "rate": "900.00000",
- "ttl": 7000,
- "type": "transfer"
+ "rate": "900.00000"
},
+ "priority": "normal",
"status": "completed",
"type": "transfer"
},
{
+ "application": null,
"createdAt": "2016-01-19T12:07:01.611Z",
"denomination": {
"amount": "0.01",
- "currency": "BTC",
- "pair": "BTCBTC",
- "rate": "1.00"
+ "currency": "BTC"
},
"destination": {
"address": "n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi",
@@ -825,10 +749,8 @@ curl -X GET "https://api.uphold.com/v0/reserve/transactions"
"base": "0.01",
"commission": "0.00",
"currency": "BTC",
- "description": "n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi",
"fee": "0.00",
- "rate": "1.00",
- "type": "external"
+ "rate": "1.00"
},
"fees": [{
"amount": "0.0002",
@@ -843,39 +765,25 @@ curl -X GET "https://api.uphold.com/v0/reserve/transactions"
"type": "withdrawal"
}],
"id": "99191bf6-52d8-4f29-92e8-676b68c9a85b",
- "message": null,
- "network": "bitcoin",
- "normalized": [{
- "amount": "9.18",
- "commission": "0.00",
- "currency": "USD",
- "fee": "0.18",
- "rate": "900.00000"
- }],
"origin": {
- "CardId": "d42999c4-30c9-4a61-889c-62a4050bce88",
"amount": "0.0102",
"base": "0.01",
"commission": "0.00",
"currency": "BTC",
- "description": "Nuno Sousa",
"fee": "0.0002",
"rate": "1.00",
"sources": [{
"amount": "0.0102",
"id": "390ed0ab-c014-43f3-868a-8ea3ea56025e"
- }],
- "type": "card"
+ }]
},
"params": {
"currency": "BTC",
"margin": "0.00",
"pair": "BTCBTC",
- "progress": "1",
- "rate": "1.00",
- "ttl": 7000,
- "type": "external/out"
+ "rate": "1.00"
},
+ "priority": "normal",
"status": "completed",
"type": "withdrawal"
}]
@@ -885,12 +793,16 @@ See also: [Transparency: Reservechain](#the-reservechain)
Requests the public view of all transactions in the reserve.
-To access this endpoint, an API key is required.
+To access this endpoint, an OAuth access token obtained by a client with the `authorization_code` grant is required.
### Request
`GET https://api.uphold.com/v0/reserve/transactions`
+
+ Requires the reserve:read scope for Uphold Connect applications.
+
+
This endpoint supports [Pagination](#pagination).
### Response
@@ -915,9 +827,7 @@ curl -X GET "https://api.uphold.com/v0/reserve/transactions/a97bb994-6e24-4a89-b
"createdAt": "2014-08-27T00:01:11.616Z",
"denomination": {
"amount": "1.00",
- "currency": "USD",
- "pair": "USDUSD",
- "rate": "1.00"
+ "currency": "USD"
},
"destination": {
"amount": "1.00",
@@ -956,6 +866,8 @@ See also: [Transparency: Reservechain](#the-reservechain)
Requests the public view of a specific transaction.
+Unlike [Get All Transactions (Public)](#get-all-transactions-public), this endpoint requires no authentication.
+
### Request
`GET https://api.uphold.com/v0/reserve/transactions/:id`
@@ -965,7 +877,7 @@ Requests the public view of a specific transaction.
Returns a [Transaction Object](#transaction-object).
- Note that you will only receive the list of committed transactions.
+ Note that only committed transactions can be retrieved through this endpoint.
## Transaction Limit Errors
diff --git a/_travelrule.md b/_travelrule.md
index d7289a6..6bfb4d7 100644
--- a/_travelrule.md
+++ b/_travelrule.md
@@ -59,7 +59,7 @@ Retrieves the details of the pending travel rule request associated with a depos
`GET https://api.uphold.com/v0/me/travel-rule/transactions/:transactionId/request`
- Requires the transactions:read scope for Uphold Connect applications. Returns a 401 HTTP error if the token is missing or invalid, or a 403 HTTP error if the required scope is not present.
+ Requires the transactions:read scope for Uphold Connect applications. Returns a 401 HTTP error if the token is missing or invalid, or a 400 HTTP error with code invalid_scope if the required scope is not present.
Returns a 404 HTTP error if no pending travel rule request is associated with the given transaction.
@@ -127,7 +127,7 @@ Retrieves the details of a pending travel rule request for a withdrawal, using t
`GET https://api.uphold.com/v0/me/travel-rule/requests/:requestForInformationId`
- Requires the transactions:read scope for Uphold Connect applications. Returns a 401 HTTP error if the token is missing or invalid, or a 403 HTTP error if the required scope is not present.
+ Requires the transactions:read scope for Uphold Connect applications. Returns a 401 HTTP error if the token is missing or invalid, or a 400 HTTP error with code invalid_scope if the required scope is not present.
The :requestForInformationId must be owned by the authenticated user. A 404 HTTP error is returned otherwise.
@@ -163,7 +163,7 @@ For withdrawals, this must be submitted before [committing the quote](#step-2-co
`POST https://api.uphold.com/v0/me/travel-rule/requests/:requestForInformationId`
- Requires the transactions:withdraw scope for Uphold Connect applications. Returns a 401 HTTP error if the token is missing or invalid, or a 403 HTTP error if the required scope is not present.
+ Requires the transactions:withdraw scope for Uphold Connect applications. Returns a 401 HTTP error if the token is missing or invalid, or a 400 HTTP error with code invalid_scope if the required scope is not present.
The :requestForInformationId must be owned by the authenticated user. A 404 HTTP error is returned otherwise.