<@U04UQ68083H> Show an example template for one ti...
# ory-copilot
c
@chilly-king-10285 Show an example template for one time code emails that displays a different logo depending on the contextual data sent through.
b
A message from kapa.ai
Certainly! To display a different logo in a one-time code email template based on contextual data (such as a value in the transient payload), you can use the Go template logic provided by Ory. The transient payload is accessible in the template as
.TransientPayload
. Here’s an example for a login code email (HTML version) that shows a different logo depending on a value (e.g.,
brand
) in the transient payload:
Copy code
gotmpl {{- if eq (index .TransientPayload "brand") "BrandA" -}}   <img src="https://example.com/logo-brand-a.png" alt="Brand A Logo" /> {{- else if eq (index .TransientPayload "brand") "BrandB" -}}   <img src="https://example.com/logo-brand-b.png" alt="Brand B Logo" /> {{- else -}}   <img src="https://example.com/default-logo.png" alt="Default Logo" /> {{- end }}  <p>Hello,</p> <p>Your one-time login code is: <strong>{{ .LoginCode }}</strong></p> <p>This code will expire in {{ .ExpiresInMinutes }} minutes.</p>
- The value for
brand
is passed in the transient payload when initiating the flow. - The template uses Go’s
if
and
else
logic to select the appropriate logo. - You can use this approach for any one-time code email template (login, registration, etc.) by referencing the correct code variable (
.LoginCode
,
.RegistrationCode
, etc.). For more details on using transient payloads in templates, see the official documentation: [Transient payload in templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#transient-payload-in-templates). If you need to customize based on other contextual data, simply adjust the key you check in
.TransientPayload
accordingly.
c
How do I send the .TransientPayload data?
@chilly-king-10285 How do I send the .TransientPayload data?
b
A message from kapa.ai
You can send the
.TransientPayload
data by including a
transient_payload
field in the request body when submitting a self-service flow, such as registration, login, or settings. This field should be a JSON object containing the contextual data you want to pass. The data in
transient_payload
will be forwarded to webhooks and made available in email templates, but it will not be persisted by Ory. Example: Submitting a registration flow with transient_payload
Copy code
json {   "method": "password",   "csrf_token": "your-csrf-token",   "traits": {     "email": "<mailto:user@example.com|user@example.com>"   },   "password": "verystrongpassword",   "transient_payload": {     "brand": "BrandA",     "example_key": "This is an example value"   } }
When you send this payload to the registration endpoint, the
transient_payload
data will be accessible in your email templates as
.TransientPayload
(e.g.,
{{ index .TransientPayload "brand" }}
) [Customizing template content for specific users](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#transient-payload-in-templates). This approach works similarly for other flows (login, settings, etc.)—just include the
transient_payload
field in your request body as shown above. For more details and SDK usage, see the [Github issue discussion](https://github.com/ory/network/issues/187).
c
@chilly-king-10285 Show an example using: const init_otc_login_result = await axios.post( IMG_API_URL + “/api/accounts/login/init-otc-login”, { email: email }, { headers: { “Content-Type”: “application/json” }, } )
b
A message from kapa.ai
I'm sorry, but the knowledge sources do not contain information about an endpoint called
/api/accounts/login/init-otc-login
or how to use it with Axios. The Ory documentation describes how to initiate and update self-service flows (such as login or registration) using the official Ory APIs, but there is no mention of an
init-otc-login
endpoint or a usage example with Axios for this specific path. If you are looking to initiate a login flow with Ory Kratos and include a
transient_payload
, you would typically interact with the Ory endpoints (such as
/self-service/login/api
or
/self-service/login/browser
) and include the
transient_payload
in your request body. However, without more details or documentation about the custom endpoint you referenced, I cannot provide a reliable example. If you need an example for the official Ory login flow with
transient_payload
, please clarify, and I can provide that based on the available documentation.
c
@chilly-king-10285 Show an example using: const flow_result = await axios.get(
${ORY_BASE_URL}/self-service/login/api
) const flow = flow_result.data const init_otc_login_result = await axios.post( flow.ui.action, { method: “code”, identifier: email }, { headers: { “Content-Type”: “application/json” }, } )
b
A message from kapa.ai
Certainly! Here’s how you can use Axios to initiate a login flow with Ory Kratos and then submit a one-time code (OTC) login request, based on the official Ory API and the knowledge sources:
Copy code
js // Step 1: Initialize the login flow for native/API clients const flow_result = await axios.get(`${ORY_BASE_URL}/self-service/login/api`) const flow = flow_result.data  // Step 2: Submit the login flow with the "code" method and identifier (email) const init_otc_login_result = await <http://axios.post|axios.post>(   flow.ui.action,   {     method: "code",     identifier: email     // You can also include transient_payload here if needed     // transient_payload: { brand: "BrandA" }   },   {     headers: {       "Content-Type": "application/json"     },   } )
Notes: - The first request initializes the login flow and retrieves the flow object, including the
ui.action
URL for submission. - The second request submits the login form using the
"code"
method and the user's identifier (email). - If you want to include contextual data (such as for
.TransientPayload
in email templates), add a
transient_payload
field to the POST body as described in the documentation. - This flow matches the Ory Kratos API for native/mobile clients and is supported by the knowledge sources [API flows: Native Mobile & Desktop Apps, Command Line Interfaces, Smart TVs and more](https://www.ory.sh/docs/kratos/self-service#api-flows-native-mobile--desktop-apps-command-line-interfaces-smart-tvs-and-more) and [Submit flows](https://www.ory.sh/docs/kratos/bring-your-own-ui/custom-ui-basic-integration#submit-flows). If you need to include
transient_payload
, your POST body would look like:
Copy code
js {   method: "code",   identifier: email,   transient_payload: { brand: "BrandA" } }
This will make the
brand
value available in your email templates as
.TransientPayload.brand
[Customizing template content for specific users](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#transient-payload-in-templates).
c
@chilly-king-10285 Where do I change the “From” display for one-time code emails?
b
A message from kapa.ai
To change the “From” display (sender name and email address) for one-time code emails in Ory, you must configure your own SMTP server. This is because the default Ory Network sender address cannot be changed unless you supply your own SMTP server. You can set the
from_name
and
from_address
fields in your Ory Identities configuration under the
courier.smtp
section. For example:
Copy code
yaml courier:   delivery_strategy: smtp   smtp:     connection_uri: <smtp://username:password@server:port/>     from_address: <mailto:hello@example.org|hello@example.org>     from_name: My Company
After updating your configuration, upload it to your Ory project. This will set the sender name and address for all emails, including one-time code emails. If you do not configure a custom SMTP server, the default sender will be used and cannot be changed [SMTP Courier address not settable](https://www.ory.sh/docs/debug/smtp-courier-1) [Send emails using your SMTP server](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp).
c
@chilly-king-10285 Where do I change it in the Ory Console
b
A message from kapa.ai
To change the "From" display (sender name and email address) for one-time code emails in the Ory Console, go to AuthenticationEmail configuration. There, you can configure your own SMTP server and set the sender name (
from_name
) and sender address (
from_address
). This will update the "From" display for all emails, including one-time code emails. Note that you must use your own SMTP server to change these values; the default sender cannot be changed otherwise [Send emails using your SMTP server](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp) [SMTP Courier address not settable](https://www.ory.sh/docs/debug/smtp-courier-1).
c
@chilly-king-10285 How do I load the template tinto the config
b
A message from kapa.ai
To load a custom email template into your Ory configuration, you need to encode your template (HTML or plaintext) in Base64 and add it to your configuration file under the appropriate template section. Here’s how you can do it: 1. Encode your template Use a command like the following to encode your template:
Copy code
sh    echo "Your custom template content" | base64
Or use an online tool such as [base64encode.org](https://www.base64encode.org/). 2. Add the encoded template to your config In your configuration file (e.g.,
identity-config.yaml
), add the Base64-encoded template under the correct template path. For example, for a one-time code login email:
Copy code
yaml    courier:      smtp:        from_name: MyProject via Ory        templates:          login_code:            valid:              email:                body:                  html: "<base64://ENCODED_HTML_TEMPLATE>"                  plaintext: "<base64://ENCODED_PLAINTEXT_TEMPLATE>"
Make sure to prefix the encoded string with
base64://
. 3. Upload the updated config Use the Ory CLI to upload your updated configuration:
Copy code
sh    ory update identity-config --project <project-id> --workspace <workspace-id> --file updated_config.yaml
Note: - In Ory Network, only Base64-encoded templates are supported. You cannot use
file://
or
http://
URIs for templates in Ory Network; these are only available in self-hosted Ory Kratos. If you use unsupported methods, the system will fall back to the default templates [Using custom message templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#using-custom-message-templates). - For self-hosted Ory Kratos, you can also use
file://
or
http://
URIs in addition to
base64://
 [Email templates in self-hosted Ory Kratos](https://www.ory.sh/docs/kratos/self-hosted/mail-courier-templates). This process allows you to version and manage your email templates as part of your configuration [Email Templates (GitOps)](https://www.ory.sh/docs/guides/gitops#email-templates).
c
@chilly-king-10285 SHow the cli command to get the identity-config.yaml
b
A message from kapa.ai
To get the
identity-config.yaml
using the Ory CLI, use the following command:
Copy code
sh ory get identity-config --project <project-id> --workspace <workspace-id> --format yaml > identity-config.yaml
Replace
<project-id>
and
<workspace-id>
with your actual project and workspace identifiers. This command will download your Ory Identities configuration in YAML format and save it as
identity-config.yaml
 [ory get identity-config](https://www.ory.sh/docs/cli/ory-get-identity-config#ory-get-identity-config).
c
@chilly-king-10285 Which email template do I want to update for use with the ${ORY_BASE_URL}/self-service/login/api
b
A message from kapa.ai
For the
${ORY_BASE_URL}/self-service/login/api
endpoint, when you are using the one-time code (OTC) login method, the email template you want to update is the
login_code.valid
template. This template is used to send the one-time login code to users during the login flow with the "code" method. You can customize this template in your configuration under:
Copy code
yaml courier:   smtp:     templates:       login_code:         valid:           email:             body:               html: "<base64://ENCODED_HTML_TEMPLATE>"               plaintext: "<base64://ENCODED_PLAINTEXT_TEMPLATE>"
This is confirmed in the documentation: > When you enable the one-time code method the login flow will need to send out an email to users signing in through the one-time code method. The system will then use the
login_code.valid
template to send the login code to the user. [Email templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates) So, for OTC login via the login API, update the
login_code.valid
email template.
c
@chilly-king-10285 Why am I seeing
{}
as values in my YAML when I get the config: courier: delivery_strategy: smtp smtp: connection_uri: smtp://smtp%40mailtrap.io:f574de9c31a89fe7cda8653c9869e6c0@live.smtp.mailtrap.io:587 from_address: engineering@insightmediagroup.io from_name: Verification Code headers: {} templates: login_code: valid: email: body: {} sms: body: {}
b
A message from kapa.ai
When you see
{}
as values in your YAML configuration for sections like
body
under
templates
, it means that no custom template has been set for that template type. In Ory, if you do not provide a custom template (for example, a Base64-encoded HTML or plaintext template), the configuration will show an empty object (
{}
), and Ory will use the built-in default template for that message type. For example:
Copy code
yaml login_code:   valid:     email:       body: {}     sms:       body: {}
This means that both the email and SMS bodies for the
login_code.valid
template are not customized, so the system will fall back to the default templates provided by Ory. To use your own template, you need to encode your template in Base64 and add it to the config, like this:
Copy code
yaml login_code:   valid:     email:       body:         html: "<base64://ENCODED_HTML_TEMPLATE>"         plaintext: "<base64://ENCODED_PLAINTEXT_TEMPLATE>"
If you do not do this, the config will show
{}
and the default will be used [Using custom message templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#using-custom-message-templates).
c
@chilly-king-10285 Can I load a golang template into the Ory Console UI?
b
A message from kapa.ai
You cannot directly load a raw Go template file into the Ory Console UI. According to the knowledge sources, to use a custom email template in Ory Network (including via the Console UI), you must first encode your template (which can be written using Go template syntax) in Base64 and then add it to your configuration. The Ory Console UI does not accept file uploads or raw Go template text; it only accepts Base64-encoded template strings as part of the configuration process [Using custom message templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#using-custom-message-templates). If you try to provide a template in any other format (such as a file path or URL), it will not be accepted, and the system will fall back to the default templates. This is a security and compatibility measure in Ory Network [Github Issue: Custom email templates don't allow URLs](https://github.com/ory/network/issues/115). In summary: - Write your template using Go template syntax. - Encode it in Base64. - Paste the Base64 string into the Ory Console UI configuration. Direct upload or pasting of raw Go template files is not supported.
c
@chilly-king-10285 Show the base64 cli command from a file called “ory-otc-email-template.tmpl”
b
A message from kapa.ai
To encode a file called
ory-otc-email-template.tmpl
to Base64, use the following command:
Copy code
sh base64 < ory-otc-email-template.tmpl
This command reads the contents of
ory-otc-email-template.tmpl
and outputs the Base64-encoded string, which you can then use in your Ory configuration as required [Email Templates (GitOps)](https://www.ory.sh/docs/guides/gitops#email-templates) [Using custom message templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#using-custom-message-templates).
c
@chilly-king-10285 Is this correct: login_code: valid: email: body: html: “base64://e3sgZGVmaW5lICJib2R5IiB9fQo8IURPQ1RZUEUgaHRtbD4KPGh0bWwKCWxhbmc9ImVuIgoJeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWwiCgl4bWxuczp2PSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnZtbCIKCXhtbG5zOm89InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOm9mZmljZSIKPgoJPGhlYWQ+CgkJPHRpdGxlPllvdXIgb25lLXRpbWUgY29kZSBmb3IgeW91ciBhY2NvdW50IGlzIHt7IC5Mb2dpbkNvZGUgfX08L3RpdGxlPgoJCTwhLS1baWYgIW1zb10+PCEtLT4KCQk8bWV0YSBodHRwLWVxdWl2PSJYLVVBLUNvbXBhdGlibGUiIGNvbnRlbnQ9IklFPWVkZ2UiIC8+CgkJPCEtLTwhW2VuZGlmXS0tPgoJCTxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgoJCTxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MSIgLz4KCQk8bWV0YSBuYW1lPSJjb2xvci1zY2hlbWUiIGNvbnRlbnQ9ImxpZ2h0IGRhcmsiIC8+CgkJPG1ldGEgbmFtZT0ic3VwcG9ydGVkLWNvbG9yLXNjaGVtZXMiIGNvbnRlbnQ9ImxpZ2h0IGRhcmsiIC8+CgkJPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCQkJI291dGxvb2sgYSB7IHBhZGRpbmc6IDA7IH0KCQkJYm9keSB7IG1hcmdpbjogMDsgcGFkZGluZzogMDsgLXdlYmtpdC10ZXh0LXNpemUtYWRqdXN0OiAxMDAlOyAtbXMtdGV4dC1zaXplLWFkanVzdDogMTAwJTsgfQoJCQl0YWJsZSwgdGQgeyBib3JkZXItY29sbGFwc2U6IGNvbGxhcHNlOyBtc28tdGFibGUtbHNwYWNlOiAwcHQ7IG1zby10YWJsZS1yc3BhY2U6IDBwdDsgfQoJCQlpbWcgeyBib3JkZXI6IDA7IGhlaWdodDogYXV0bzsgbGluZS1oZWlnaHQ6IDEwMCU7IG91dGxpbmU6IG5vbmU7IHRleHQtZGVjb3JhdGlvbjogbm9uZTsgLW1zLWludGVycG9sYXRpb24tbW9kZTogYmljdWJpYzsgfQoJCQlwIHsgZGlzcGxheTogYmxvY2s7IG1hcmdpbjogMDsgfQoJCQlhW3gtYXBwbGUtZGF0YS1kZXRlY3RvcnNdIHsgY29sb3I6IGluaGVyaXQgIWltcG9ydGFudDsgdGV4dC1kZWNvcmF0aW9uOiBub25lICFpbXBvcnRhbnQ7IH0KCQkJdSArIC5lbWFpbGlmeSBhIHsgY29sb3I6IGluaGVyaXQgIWltcG9ydGFudDsgdGV4dC1kZWNvcmF0aW9uOiBub25lICFpbXBvcnRhbnQ7IH0KCQkJI01lc3NhZ2VWaWV3Qm9keSBhIHsgY29sb3I6IGluaGVyaXQgIWltcG9ydGFudDsgdGV4dC1kZWNvcmF0aW9uOiBub25lICFpbXBvcnRhbnQ7IH0KCQk8L3N0eWxlPgoJPC9oZWFkPgoJPGJvZHkKCQlsYW5nPSJlbiIKCQlsaW5rPSIjREQwMDAwIgoJCXZsaW5rPSIjREQwMDAwIgoJCWNsYXNzPSJlbWFpbGlmeSIKCQlzdHlsZT0ibXNvLWxpbmUtaGVpZ2h0LXJ1bGU6IGV4YWN0bHk7IG1zby1oeXBoZW5hdGU6IG5vbmU7IHdvcmQtc3BhY2luZzogbm9ybWFsOyBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOyIKCT4KCQk8ZGl2IGNsYXNzPSJiZyIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmZmZmYiIGxhbmc9ImVuIj4KCQkJPGRpdiBjbGFzcz0iciBwci0xNiBwbC0xNiIgc3R5bGU9ImJhY2tncm91bmQ6ICNmZmZmZmU7IG1hcmdpbjogMHB4IGF1dG87IG1heC13aWR0aDogNjAwcHg7Ij4KCQkJCTx0YWJsZSBhbGlnbj0iY2VudGVyIiBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCIgcm9sZT0icHJlc2VudGF0aW9uIiBzdHlsZT0id2lkdGg6IDEwMCU7IGJhY2tncm91bmQ6ICNmZmZmZmU7Ij4KCQkJCQk8dGJvZHk+CgkJCQkJCTx0cj4KCQkJCQkJCTx0ZCBzdHlsZT0iYm9yZGVyOiBub25lOyBkaXJlY3Rpb246IGx0cjsgZm9udC1zaXplOiAwOyBwYWRkaW5nOiAzMnB4IDMycHggNDhweCAzMnB4OyB0ZXh0LWFsaWduOiBsZWZ0OyI+CgkJCQkJCQkJPGRpdiBjbGFzcz0ieGM1MzYgb2dmIGMiIHN0eWxlPSJmb250LXNpemU6IDA7IHRleHQtYWxpZ246IGxlZnQ7IGRpcmVjdGlvbjogbHRyOyBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHZlcnRpY2FsLWFsaWduOiB0b3A7IHdpZHRoOiAxMDAlOyI+CgkJCQkJCQkJCTx0YWJsZSBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIwIiBjZWxsc3BhY2luZz0iMCIgcm9sZT0icHJlc2VudGF0aW9uIiBzdHlsZT0iYm9yZGVyOiBub25lOyB2ZXJ0aWNhbC1hbGlnbjogdG9wOyIgd2lkdGg9IjEwMCUiPgoJCQkJCQkJCQkJPHRib2R5PgoJCQkJCQkJCQkJCTx0cj4KCQkJCQkJCQkJCQkJPHRkIGFsaWduPSJsZWZ0IiBjbGFzcz0ieCBtIiBzdHlsZT0iZm9udC1zaXplOiAwOyBwYWRkaW5nLWJvdHRvbTogMDsgd29yZC1icmVhazogYnJlYWstd29yZDsiPgoJCQkJCQkJCQkJCQkJPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogbGVmdDsiPgoJCQkJCQkJCQkJCQkJCXt7LSAkYnJhbmQgOj0gaW5kZXggLlBheWxvYWQgImJyYW5kIiAtfX0KCQkJCQkJCQkJCQkJCQl7ey0gaWYgZXEgJGJyYW5kICJ0aGVuZXdzdGFzY2siIC19fQoJCQkJCQkJCQkJCQkJCQlUaGUgTmV3IFN0YWNrCgkJCQkJCQkJCQkJCQkJCTxpbWcgc3JjPSJodHRwczovL2Nkbi5leGFtcGxlLmNvbS9sb2dvcy9hY21lLnBuZyIgYWx0PSJBY21lIExvZ28iIHdpZHRoPSIxMjAiIHN0eWxlPSJtYXJnaW4tYm90dG9tOiAyNHB4OyIgLz4KCQkJCQkJCQkJCQkJCQl7ey0gZWxzZSBpZiBlcSAkYnJhbmQgInRvd2FyZHNkYXRhc2NpZW5jZSIgLX19CgkJCQkJCQkJCQkJCQkJCVRvd2FyZHMgRGF0YSBTY2llbmNlCgkJCQkJCQkJCQkJCQkJCTxpbWcgc3JjPSJodHRwczovL2Nkbi5leGFtcGxlLmNvbS9sb2dvcy9nbG9iZXgucG5nIiBhbHQ9Ikdsb2JleCBMb2dvIiB3aWR0aD0iMTIwIiBzdHlsZT0ibWFyZ2luLWJvdHRvbTogMjRweDsiIC8+CgkJCQkJCQkJCQkJCQkJe3stIGVsc2UgaWYgZXEgJGJyYW5kICJyb2FkbWFwIiAtfX0KCQkJCQkJCQkJCQkJCQkJUm9hZG1hcAoJCQkJCQkJCQkJCQkJCQk8aW1nIHNyYz0iaHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20vbG9nb3MvZ2xvYmV4LnBuZyIgYWx0PSJHbG9iZXggTG9nbyIgd2lkdGg9IjEyMCIgc3R5bGU9Im1hcmdpbi1ib3R0b206IDI0cHg7IiAvPgoJCQkJCQkJCQkJCQkJCXt7LSBlbmQgfX0KCQkJCQkJCQkJCQkJCQk8cCBzdHlsZT0iZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogNjAwOyBjb2xvcjogIzBmMTcyYTsgbGluZS1oZWlnaHQ6IDE1MCU7Ij5Zb3VyIG9uZS10aW1lIGNvZGUgZm9yIHlvdXIgYWNjb3VudCBpcyB7eyAuTG9naW5Db2RlIH19PC9wPgoJCQkJCQkJCQkJCQkJPC9kaXY+CgkJCQkJCQkJCQkJCTwvdGQ+CgkJCQkJCQkJCQkJPC90cj4KCQkJCQkJCQkJCQk8dHI+PHRkIHN0eWxlPSJoZWlnaHQ6IDIwcHg7Ij48L3RkPjwvdHI+CgkJCQkJCQkJCQkJPHRyPgoJCQkJCQkJCQkJCQk8dGQgYWxpZ249ImxlZnQiIGNsYXNzPSJ4IG0iIHN0eWxlPSJmb250LXNpemU6IDA7IHBhZGRpbmctYm90dG9tOiAwOyB3b3JkLWJyZWFrOiBicmVhay13b3JkOyI+CgkJCQkJCQkJCQkJCQk8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBsZWZ0OyI+CgkJCQkJCQkJCQkJCQkJPHAgc3R5bGU9ImZvbnQtc2l6ZTogMTZweDsgZm9udC13ZWlnaHQ6IDQwMDsgY29sb3I6ICMxZTI5M2I7IGxpbmUtaGVpZ2h0OiAxNTAlOyI+CgkJCQkJCQkJCQkJCQkJCUFzIHJlcXVlc3RlZCwgaGVyZSBpcyB5b3VyIG9uZS10aW1lIGNvZGUgdG8gbG9nIGluIHRvIHlvdXIgYWNjb3VudCB3aXRoIHt7ICRicmFuZCB9fToKCQkJCQkJCQkJCQkJCQk8L3A+CgkJCQkJCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCQkJCQkJPC90ZD4KCQkJCQkJCQkJCQk8L3RyPgoJCQkJCQkJCQkJCTx0cj48dGQgc3R5bGU9ImhlaWdodDogMjBweDsiPjwvdGQ+PC90cj4KCQkJCQkJCQkJCQk8dHI+CgkJCQkJCQkJCQkJCTx0ZCBhbGlnbj0ibGVmdCIgY2xhc3M9InggbSIgc3R5bGU9ImZvbnQtc2l6ZTogMDsgcGFkZGluZy1ib3R0b206IDA7IHdvcmQtYnJlYWs6IGJyZWFrLXdvcmQ7Ij4KCQkJCQkJCQkJCQkJCTxkaXYgc3R5bGU9InRleHQtYWxpZ246IGxlZnQ7Ij4KCQkJCQkJCQkJCQkJCQk8cCBzdHlsZT0iZm9udC1zaXplOiAzMnB4OyBmb250LXdlaWdodDogNDAwOyBjb2xvcjogIzFlMjkzYjsgbGV0dGVyLXNwYWNpbmc6IDFweDsgbGluZS1oZWlnaHQ6IDE1MCU7Ij4KCQkJCQkJCQkJCQkJCQkJe3sgLkxvZ2luQ29kZSB9fQoJCQkJCQkJCQkJCQkJCTwvcD4KCQkJCQkJCQkJCQkJCTwvZGl2PgoJCQkJCQkJCQkJCQk8L3RkPgoJCQkJCQkJCQkJCTwvdHI+CgkJCQkJCQkJCQkJPHRyPjx0ZCBzdHlsZT0iaGVpZ2h0OiAyMHB4OyI+PC90ZD48L3RyPgoJCQkJCQkJCQkJCTx0cj4KCQkJCQkJCQkJCQkJPHRkIGFsaWduPSJsZWZ0IiBjbGFzcz0ieCBtIiBzdHlsZT0iZm9udC1zaXplOiAwOyBwYWRkaW5nLWJvdHRvbTogMDsgd29yZC1icmVhazogYnJlYWstd29yZDsiPgoJCQkJCQkJCQkJCQkJPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogbGVmdDsiPgoJCQkJCQkJCQkJCQkJCTxwIHN0eWxlPSJmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiA0MDA7IGNvbG9yOiAjMWUyOTNiOyBsaW5lLWhlaWdodDogMTUwJTsiPgoJCQkJCQkJCQkJCQkJCQlJZiB5b3UgZGlkIG5vdCByZXF1ZXN0IHRoaXMgY29kZSwgeW91IGNhbiBpZ25vcmUgdGhpcyBlbWFpbC4KCQkJCQkJCQkJCQkJCQk8L3A+CgkJCQkJCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCQkJCQkJPC90ZD4KCQkJCQkJCQkJCQk8L3RyPgoJCQkJCQkJCQkJCTx0cj48dGQgc3R5bGU9ImhlaWdodDogMjBweDsiPjwvdGQ+PC90cj4KCQkJCQkJCQkJCQk8dHI+CgkJCQkJCQkJCQkJCTx0ZCBhbGlnbj0ibGVmdCIgY2xhc3M9IngiIHN0eWxlPSJmb250LXNpemU6IDA7IHBhZGRpbmctYm90dG9tOiAwOyB3b3JkLWJyZWFrOiBicmVhay13b3JkOyI+CgkJCQkJCQkJCQkJCQk8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBsZWZ0OyI+CgkJCQkJCQkJCQkJCQkJPHAgc3R5bGU9ImZvbnQtc2l6ZTogMTZweDsgZm9udC13ZWlnaHQ6IDQwMDsgY29sb3I6ICMxZTI5M2I7IGxpbmUtaGVpZ2h0OiAxNTAlOyI+VGhhbmsgeW91PC9wPgoJCQkJCQkJCQkJCQkJPC9kaXY+CgkJCQkJCQkJCQkJCTwvdGQ+CgkJCQkJCQkJCQkJPC90cj4KCQkJCQkJCQkJCTwvdGJvZHk+CgkJCQkJCQkJCTwvdGFibGU+CgkJCQkJCQkJPC9kaXY+CgkJCQkJCQk8L3RkPgoJCQkJCQk8L3RyPgoJCQkJCTwvdGJvZHk+CgkJCQk8L3RhYmxlPgoJCQk8L2Rpdj4KCgkJCTxkaXYgY2xhc3M9InIgcHItMTYgcGwtMTYiIHN0eWxlPSJiYWNrZ3JvdW5kOiAjZjhmYWZjOyBtYXJnaW46IDBweCBhdXRvOyBtYXgtd2lkdGg6IDYwMHB4OyI+CgkJCQk8dGFibGUgYWxpZ249ImNlbnRlciIgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiIHJvbGU9InByZXNlbnRhdGlvbiIgc3R5bGU9IndpZHRoOiAxMDAlOyBiYWNrZ3JvdW5kOiAjZjhmYWZjOyI+CgkJCQkJPHRib2R5PgoJCQkJCQk8dHI+CgkJCQkJCQk8dGQgc3R5bGU9ImJvcmRlcjogbm9uZTsgZGlyZWN0aW9uOiBsdHI7IGZvbnQtc2l6ZTogMDsgcGFkZGluZzogMzJweDsiPgoJCQkJCQkJCTxkaXYgY2xhc3M9InhjNTM2IG9nZiBjIiBzdHlsZT0iZm9udC1zaXplOiAwOyB0ZXh0LWFsaWduOiBsZWZ0OyBkaXJlY3Rpb246IGx0cjsgZGlzcGxheTogaW5saW5lLWJsb2NrOyB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlOyB3aWR0aDogMTAwJTsiPgoJCQkJCQkJCQk8dGFibGUgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMCIgY2VsbHNwYWNpbmc9IjAiIHJvbGU9InByZXNlbnRhdGlvbiIgc3R5bGU9ImJvcmRlcjogbm9uZTsgdmVydGljYWwtYWxpZ246IG1pZGRsZTsiIHdpZHRoPSIxMDAlIj4KCQkJCQkJCQkJCTx0Ym9keT4KCQkJCQkJCQkJCQk8dHI+CgkJCQkJCQkJCQkJCTx0ZCBhbGlnbj0ibGVmdCIgY2xhc3M9IngiIHN0eWxlPSJmb250LXNpemU6IDA7IHBhZGRpbmctYm90dG9tOiAwOyB3b3JkLWJyZWFrOiBicmVhay13b3JkOyI+CgkJCQkJCQkJCQkJCQk8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBsZWZ0OyI+CgkJCQkJCQkJCQkJCQkJPHAgc3R5bGU9ImZvbnQtc2l6ZTogMTRweDsgZm9udC13ZWlnaHQ6IDQwMDsgY29sb3I6ICM2NDc0OGI7IGxpbmUtaGVpZ2h0OiAxNTAlOyI+CgkJCQkJCQkJCQkJCQkJCVNlY3VyZWQgYnkmbmJzcDsKCQkJCQkJCQkJCQkJCQkJPGEgaHJlZj0iaHR0cHM6Ly93d3cub3J5LnNoL2FjY291bnQtc2VjdXJpdHkiIHRhcmdldD0iX2JsYW5rIiBzdHlsZT0iY29sb3I6ICM2MzY2ZjE7IGZvbnQtd2VpZ2h0OiA2MDA7IHRleHQtZGVjb3JhdGlvbjogbm9uZTsiPgoJCQkJCQkJCQkJCQkJCQkJT3J5CgkJCQkJCQkJCQkJCQkJCTwvYT4KCQkJCQkJCQkJCQkJCQk8L3A+CgkJCQkJCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCQkJCQkJPC90ZD4KCQkJCQkJCQkJCQk8L3RyPgoJCQkJCQkJCQkJPC90Ym9keT4KCQkJCQkJCQkJPC90YWJsZT4KCQkJCQkJCQk8L2Rpdj4KCQkJCQkJCTwvdGQ+CgkJCQkJCTwvdHI+CgkJCQkJPC90Ym9keT4KCQkJCTwvdGFibGU+CgkJCTwvZGl2PgoJCTwvZGl2PgoJPC9ib2R5Pgo8L2h0bWw+Cnt7IGVuZCB9fQo=”
b
A message from kapa.ai
Yes, your configuration is correct in structure. For the Ory Network, when you want to use a custom template for the one-time code login email, you should provide the Base64-encoded template under:
Copy code
yaml login_code:   valid:     email:       body:         html: "<base64://...>"
- The value after
base64://
should be the Base64-encoded content of your Go template file (for example, from
ory-otc-email-template.tmpl
). - You can also add a
plaintext
version for plain text emails, which is required for full compatibility. Important notes: - Make sure you use straight quotes (
"
) and not curly quotes (
or
) in your YAML, as curly quotes can cause parsing errors. - The structure you posted matches the documented approach for loading custom templates in Ory Network. If you see your template rendered as expected in emails, your setup is correct [Using custom message templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#using-custom-message-templates). - If you only provide the
html
version, Ory will use it for HTML-capable clients and fall back to the default plaintext template for others unless you also provide a
plaintext
version [Mandatory template formats](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#mandatory-template-formats). So, your YAML is correct for setting a custom HTML template for the one-time code login email, as long as the Base64 content is valid and quotes are straight.
c
@chilly-king-10285 If I don’t provide a plaintext version, will it default the default template?
b
A message from kapa.ai
Yes, if you do not provide a
plaintext
version of your custom template, Ory will fall back to the default plaintext template when a plaintext email is required. The documentation states that both
html
and
plaintext
versions are mandatory, and if the system can't use the custom templates, it falls back to the built-in templates [Mandatory template formats](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#mandatory-template-formats).
c
@chilly-king-10285 Show how to load the identity config into my project.
b
A message from kapa.ai
To load the identity config into your Ory project, use the Ory CLI command
ory update identity-config
. Here’s how you do it: 1. Make sure your updated identity config file (e.g.,
identity-config.yaml
) is ready. 2. Run the following command, replacing
<project-id>
and
<workspace-id>
with your actual values:
Copy code
sh ory update identity-config --project <project-id> --workspace <workspace-id> --file identity-config.yaml
This command will upload and apply your identity configuration to your Ory project [ory update identity-config](https://www.ory.sh/docs/cli/ory-update-identity-config#ory-update-identity-config).
c
@chilly-king-10285 I’ve updated my config per the instructions and now when the email arrives the body is blank.
b
A message from kapa.ai
If the email body is blank after updating your config, there are a few likely causes based on the knowledge sources: 1. Missing or Invalid Template Content: If you provide a custom template but the content is empty, invalid, or not properly Base64-encoded, Ory may not be able to render the email body. Ensure your template is correctly written, encoded, and included in the config with the
base64://
prefix [Using custom message templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#using-custom-message-templates). 2. Only One Format Provided: If you provide only the
html
or only the
plaintext
version, and the recipient’s email client requires the other, Ory will fall back to the default template for the missing format. If the default is not available or there’s a misconfiguration, the body may appear blank [Mandatory template formats](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#mandatory-template-formats). 3. Template Rendering Errors: If your template contains errors (such as referencing missing variables or invalid Go template syntax), Ory may fail to render the body. In such cases, Ory is supposed to fall back to the default template, but if that also fails, the body could be blank. The documentation notes that missing or unexpected values in templates can cause rendering errors, and Ory will use the default template if possible [Customizing template content for specific users](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#customizing-template-content-for-specific-users). 4. Incorrect YAML Formatting: Ensure you are using straight quotes (
"
) and not curly quotes (
“”
), and that your YAML structure matches the expected format. What you can do: - Double-check your Base64-encoded template content and ensure it is valid and not empty. - Make sure both
html
and
plaintext
versions are provided. - Check for template syntax errors. - Review the [Email Delivery](https://console.ory.sh/projects/current/email-delivery) dashboard in the Ory Console for error messages related to email delivery or template rendering [Troubleshooting](https://www.ory.sh/docs/kratos/emails-sms/sending-emails-smtp#troubleshooting). If after these checks the issue persists, the knowledge sources do not provide further troubleshooting steps for blank email bodies.
c
@chilly-king-10285 If I’m passing a property called
origin
to the template, is this the correct way to reference it: {{- $origin := index .Payload “origin” -}}
b
A message from kapa.ai
The knowledge sources do not explicitly mention a
.Payload
object or the use of
index .Payload "origin"
in Ory email templates. According to the documentation, when passing additional data to templates (such as with
transient_payload
), you should access it using
.TransientPayload
. For example, if you pass an
origin
property in the
transient_payload
, you would reference it in your template like this:
Copy code
gotmpl {{- $origin := index .TransientPayload "origin" -}}
There is no mention of a
.Payload
object in the context of Ory email templates in the provided knowledge sources [Transient payload in templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#transient-payload-in-templates). If you are using a different mechanism to pass data, or if
.Payload
is specific to your custom implementation, the knowledge sources do not provide information about that. For standard Ory flows, use
.TransientPayload
.
c
@chilly-king-10285 Should it not be: {{- $origin := index .TransientPayload.Origin -}}
b
A message from kapa.ai
No, it should not be
{{- $origin := index .TransientPayload.Origin -}}
. According to the Ory documentation, when accessing a property (such as
origin
) from the
transient_payload
in your email template, you should use the
index
function with the key as a string, like this:
Copy code
gotmpl {{- $origin := index .TransientPayload "origin" -}}
This is the correct way to access the
origin
property. The dot notation (
.TransientPayload.Origin
) is not supported for dynamic keys in Go templates as used by Ory. Always use the
index
function for keys in maps like
TransientPayload
 [Transient payload in templates](https://www.ory.sh/docs/kratos/emails-sms/custom-email-templates#transient-payload-in-templates).