Skip to content

Foreign Exchange Pydantic Models

In order to simplify and standardize the data that is passed between the client and the Revolut Business API, PyRevolut uses Pydantic models to define the structure of the data. Below are the Pydantic models used by the Foreign Exchange endpoint.


ResourceForeignExchange

Bases: BaseModel

Foreign Exchange resource model.

Source code in pyrevolut/api/foreign_exchange/resources/foreign_exchange.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class ResourceForeignExchange(BaseModel):
    """
    Foreign Exchange resource model.
    """

    model_config = ConfigDict(
        populate_by_name=True,
        from_attributes=True,
    )

    class ModelFrom(ModelBaseAmount):
        """
        The money to sell.
        """

        pass

    class ModelTo(ModelBaseAmount):
        """
        The money to receive.
        """

        pass

    class ModelFee(ModelBaseAmount):
        """
        The expected fee for the transaction.
        """

        pass

    from_: Annotated[ModelFrom, Field(alias="from", description="The money to sell.")]
    to: Annotated[ModelTo, Field(description="The money to receive.")]
    rate: Annotated[float, Field(description="The proposed exchange rate.")]
    fee: Annotated[ModelFee, Field(description="The expected fee for the transaction.")]
    rate_date: Annotated[
        DateTime,
        Field(description="The date of the proposed exchange rate in ISO 8601 format."),
    ]

ModelFee

Bases: ModelBaseAmount

The expected fee for the transaction.

Source code in pyrevolut/api/foreign_exchange/resources/foreign_exchange.py
33
34
35
36
37
38
class ModelFee(ModelBaseAmount):
    """
    The expected fee for the transaction.
    """

    pass

ModelFrom

Bases: ModelBaseAmount

The money to sell.

Source code in pyrevolut/api/foreign_exchange/resources/foreign_exchange.py
19
20
21
22
23
24
class ModelFrom(ModelBaseAmount):
    """
    The money to sell.
    """

    pass

ModelTo

Bases: ModelBaseAmount

The money to receive.

Source code in pyrevolut/api/foreign_exchange/resources/foreign_exchange.py
26
27
28
29
30
31
class ModelTo(ModelBaseAmount):
    """
    The money to receive.
    """

    pass

GetExchangeRate

Get the sell exchange rate between two currencies.

Source code in pyrevolut/api/foreign_exchange/get/get_exchange_rate.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class GetExchangeRate:
    """
    Get the sell exchange rate between two currencies.
    """

    ROUTE = "/1.0/rate"

    class Params(BaseModel):
        """
        Query parameters for the endpoint.
        """

        model_config = ConfigDict(
            populate_by_name=True,
            from_attributes=True,
        )

        from_: Annotated[
            Currency,
            Field(
                alias="from",
                description="The currency that you exchange from in ISO 4217 format.",
            ),
        ]
        to: Annotated[
            Currency,
            Field(description="The currency that you exchange to in ISO 4217 format."),
        ]
        amount: Annotated[
            float | None,
            Field(
                description="The amount of the currency to exchange from. The default value is 1.00."
            ),
        ] = None

    class Response(ResourceForeignExchange):
        """
        Response model for the endpoint.
        """

        pass

Params

Bases: BaseModel

Query parameters for the endpoint.

Source code in pyrevolut/api/foreign_exchange/get/get_exchange_rate.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Params(BaseModel):
    """
    Query parameters for the endpoint.
    """

    model_config = ConfigDict(
        populate_by_name=True,
        from_attributes=True,
    )

    from_: Annotated[
        Currency,
        Field(
            alias="from",
            description="The currency that you exchange from in ISO 4217 format.",
        ),
    ]
    to: Annotated[
        Currency,
        Field(description="The currency that you exchange to in ISO 4217 format."),
    ]
    amount: Annotated[
        float | None,
        Field(
            description="The amount of the currency to exchange from. The default value is 1.00."
        ),
    ] = None

Response

Bases: ResourceForeignExchange

Response model for the endpoint.

Source code in pyrevolut/api/foreign_exchange/get/get_exchange_rate.py
44
45
46
47
48
49
class Response(ResourceForeignExchange):
    """
    Response model for the endpoint.
    """

    pass

ExchangeMoney

Exchange money using one of these methods:

Sell currency: You know the amount of currency to sell. For example, you want to exchange 135.5 USD to some EUR. Specify the amount in the from object.

Buy currency: You know the amount of currency to buy. For example, you want to exchange some USD to 200 EUR. Specify the amount in the to object.

Source code in pyrevolut/api/foreign_exchange/post/exchange_money.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
class ExchangeMoney:
    """
    Exchange money using one of these methods:

    Sell currency:
        You know the amount of currency to sell.
        For example, you want to exchange 135.5 USD to some EUR.
        Specify the amount in the from object.

    Buy currency:
        You know the amount of currency to buy.
        For example, you want to exchange some USD to 200 EUR.
        Specify the amount in the to object.
    """

    ROUTE = "/1.0/exchange"

    class Body(BaseModel):
        """
        The request body for the endpoint.
        """

        model_config = ConfigDict(
            populate_by_name=True,
            from_attributes=True,
        )

        class ModelFrom(BaseModel):
            """The details of the currency to exchange from."""

            account_id: Annotated[
                UUID, Field(description="The ID of the account to sell currency from.")
            ]
            currency: Annotated[
                Currency,
                Field(description="The currency to sell in ISO 4217 format."),
            ]
            amount: Annotated[
                float | None,
                Field(
                    description="The amount of currency. Specify ONLY if you want to sell currency."
                ),
            ] = None

        class ModelTo(BaseModel):
            """The details of the currency to exchange to."""

            account_id: Annotated[
                UUID,
                Field(
                    description="The ID of the account to receive exchanged currency into."
                ),
            ]
            currency: Annotated[
                Currency,
                Field(description="The currency to buy in ISO 4217 format."),
            ]
            amount: Annotated[
                float | None,
                Field(
                    description="The amount of currency. Specify ONLY if you want to buy currency."
                ),
            ] = None

        from_: Annotated[
            ModelFrom,
            Field(
                alias="from",
                description="The details of the currency to exchange from.",
            ),
        ]
        to: Annotated[
            ModelTo,
            Field(description="The details of the currency to exchange to."),
        ]
        reference: Annotated[
            str | None,
            Field(
                description="""
                The reference for the exchange transaction, provided by you. 
                It helps you to identify the transaction if you want to look it up later.
                """
            ),
        ] = None
        request_id: Annotated[
            str,
            Field(
                description="""
                The ID of the request, provided by you. 
                It helps you identify the transaction in your system.

                To ensure that an exchange transaction is not processed multiple 
                times if there are network or system errors, the same request_id 
                should be used for requests related to the same transaction.
                """,
                max_length=40,
            ),
        ]

        @model_validator(mode="after")
        def check_inputs(self) -> "ExchangeMoney.Body":
            """Check if the amount is specified in either the from or to object."""
            if self.from_.amount is None and self.to.amount is None:
                raise ValueError(
                    "Either the amount in the from or to object must be specified."
                )
            if self.from_.amount is not None and self.to.amount is not None:
                raise ValueError(
                    "Only the amount in either the from or to object must be specified."
                )
            return self

    class Response(BaseModel):
        """
        Response model for the endpoint.
        """

        id: Annotated[
            UUID | None, Field(description="The ID of the created transaction.")
        ] = None
        type: Annotated[
            EnumTransactionType,
            Field(
                description="The type of the transaction. For money exchange, it is 'exchange'."
            ),
        ] = EnumTransactionType.EXCHANGE
        reason_code: Annotated[
            str | None,
            Field(
                description="The reason code when the state parameter of the transaction is declined or failed."
            ),
        ] = None
        created_at: Annotated[
            DateTime,
            Field(
                description="The date and time the transaction was created in ISO 8601 format."
            ),
        ]
        completed_at: Annotated[
            DateTime | None,
            Field(
                description="The date and time the transaction was completed in ISO 8601 format."
            ),
        ] = None
        state: Annotated[
            EnumTransactionState | None,
            Field(
                description="""
                Indicates the transaction state. Possible values:

                    created:
                        The transaction has been created and is either processed asynchronously
                        or scheduled for a later time.
                    pending:
                        The transaction is pending until it's being processed.
                        If the transfer is made between Revolut accounts,
                        this state is skipped and the transaction is executed instantly.
                    completed:
                        The transaction was successful.
                    declined:
                        The transaction was unsuccessful. This can happen for a variety of reasons,
                        for example, insufficient account balance, wrong receiver information, etc.
                    failed:
                        The transaction was unsuccessful. This can happen for a variety of reasons,
                        for example, invalid API calls, blocked payments, etc.
                    reverted:
                        The transaction was reverted. This can happen for a variety of reasons,
                        for example, the receiver being inaccessible.
                """
            ),
        ] = None

Body

Bases: BaseModel

The request body for the endpoint.

Source code in pyrevolut/api/foreign_exchange/post/exchange_money.py
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class Body(BaseModel):
    """
    The request body for the endpoint.
    """

    model_config = ConfigDict(
        populate_by_name=True,
        from_attributes=True,
    )

    class ModelFrom(BaseModel):
        """The details of the currency to exchange from."""

        account_id: Annotated[
            UUID, Field(description="The ID of the account to sell currency from.")
        ]
        currency: Annotated[
            Currency,
            Field(description="The currency to sell in ISO 4217 format."),
        ]
        amount: Annotated[
            float | None,
            Field(
                description="The amount of currency. Specify ONLY if you want to sell currency."
            ),
        ] = None

    class ModelTo(BaseModel):
        """The details of the currency to exchange to."""

        account_id: Annotated[
            UUID,
            Field(
                description="The ID of the account to receive exchanged currency into."
            ),
        ]
        currency: Annotated[
            Currency,
            Field(description="The currency to buy in ISO 4217 format."),
        ]
        amount: Annotated[
            float | None,
            Field(
                description="The amount of currency. Specify ONLY if you want to buy currency."
            ),
        ] = None

    from_: Annotated[
        ModelFrom,
        Field(
            alias="from",
            description="The details of the currency to exchange from.",
        ),
    ]
    to: Annotated[
        ModelTo,
        Field(description="The details of the currency to exchange to."),
    ]
    reference: Annotated[
        str | None,
        Field(
            description="""
            The reference for the exchange transaction, provided by you. 
            It helps you to identify the transaction if you want to look it up later.
            """
        ),
    ] = None
    request_id: Annotated[
        str,
        Field(
            description="""
            The ID of the request, provided by you. 
            It helps you identify the transaction in your system.

            To ensure that an exchange transaction is not processed multiple 
            times if there are network or system errors, the same request_id 
            should be used for requests related to the same transaction.
            """,
            max_length=40,
        ),
    ]

    @model_validator(mode="after")
    def check_inputs(self) -> "ExchangeMoney.Body":
        """Check if the amount is specified in either the from or to object."""
        if self.from_.amount is None and self.to.amount is None:
            raise ValueError(
                "Either the amount in the from or to object must be specified."
            )
        if self.from_.amount is not None and self.to.amount is not None:
            raise ValueError(
                "Only the amount in either the from or to object must be specified."
            )
        return self

ModelFrom

Bases: BaseModel

The details of the currency to exchange from.

Source code in pyrevolut/api/foreign_exchange/post/exchange_money.py
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class ModelFrom(BaseModel):
    """The details of the currency to exchange from."""

    account_id: Annotated[
        UUID, Field(description="The ID of the account to sell currency from.")
    ]
    currency: Annotated[
        Currency,
        Field(description="The currency to sell in ISO 4217 format."),
    ]
    amount: Annotated[
        float | None,
        Field(
            description="The amount of currency. Specify ONLY if you want to sell currency."
        ),
    ] = None

ModelTo

Bases: BaseModel

The details of the currency to exchange to.

Source code in pyrevolut/api/foreign_exchange/post/exchange_money.py
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class ModelTo(BaseModel):
    """The details of the currency to exchange to."""

    account_id: Annotated[
        UUID,
        Field(
            description="The ID of the account to receive exchanged currency into."
        ),
    ]
    currency: Annotated[
        Currency,
        Field(description="The currency to buy in ISO 4217 format."),
    ]
    amount: Annotated[
        float | None,
        Field(
            description="The amount of currency. Specify ONLY if you want to buy currency."
        ),
    ] = None

check_inputs()

Check if the amount is specified in either the from or to object.

Source code in pyrevolut/api/foreign_exchange/post/exchange_money.py
110
111
112
113
114
115
116
117
118
119
120
121
@model_validator(mode="after")
def check_inputs(self) -> "ExchangeMoney.Body":
    """Check if the amount is specified in either the from or to object."""
    if self.from_.amount is None and self.to.amount is None:
        raise ValueError(
            "Either the amount in the from or to object must be specified."
        )
    if self.from_.amount is not None and self.to.amount is not None:
        raise ValueError(
            "Only the amount in either the from or to object must be specified."
        )
    return self

Response

Bases: BaseModel

Response model for the endpoint.

Source code in pyrevolut/api/foreign_exchange/post/exchange_money.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
class Response(BaseModel):
    """
    Response model for the endpoint.
    """

    id: Annotated[
        UUID | None, Field(description="The ID of the created transaction.")
    ] = None
    type: Annotated[
        EnumTransactionType,
        Field(
            description="The type of the transaction. For money exchange, it is 'exchange'."
        ),
    ] = EnumTransactionType.EXCHANGE
    reason_code: Annotated[
        str | None,
        Field(
            description="The reason code when the state parameter of the transaction is declined or failed."
        ),
    ] = None
    created_at: Annotated[
        DateTime,
        Field(
            description="The date and time the transaction was created in ISO 8601 format."
        ),
    ]
    completed_at: Annotated[
        DateTime | None,
        Field(
            description="The date and time the transaction was completed in ISO 8601 format."
        ),
    ] = None
    state: Annotated[
        EnumTransactionState | None,
        Field(
            description="""
            Indicates the transaction state. Possible values:

                created:
                    The transaction has been created and is either processed asynchronously
                    or scheduled for a later time.
                pending:
                    The transaction is pending until it's being processed.
                    If the transfer is made between Revolut accounts,
                    this state is skipped and the transaction is executed instantly.
                completed:
                    The transaction was successful.
                declined:
                    The transaction was unsuccessful. This can happen for a variety of reasons,
                    for example, insufficient account balance, wrong receiver information, etc.
                failed:
                    The transaction was unsuccessful. This can happen for a variety of reasons,
                    for example, invalid API calls, blocked payments, etc.
                reverted:
                    The transaction was reverted. This can happen for a variety of reasons,
                    for example, the receiver being inaccessible.
            """
        ),
    ] = None