Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Still stuck after going through our documentation? Feel free to reach out to us for some support help. There are 2 ways for you to get in touch with us:
Live chat: use the widget in the app.
Support ticket: create a ticket here.
Creating a Coinos wallet is one of the simplest ways to start using Flash. There’s no need to download any app, and the process is quick and straightforward. Follow these steps to set up your Coinos wallet and link it to Flash.
Access Coinos Click here to visit the Coinos registration page.
Register Your Account Choose a username and password, then click Save. Your wallet will be created instantly.
Open Wallet Settings On your Coinos wallet homepage, click the gear icon (⚙️).
Reveal Your NWC String Select Reveal NWC, and copy the string of letters and numbers displayed. This is your unique NWC string.
Add Wallet in Flash In the , create a new wallet and give it a name, such as "John Coinos."
Select NWC Option Choose the Nostr Wallet Connect option in the setup interface.
Paste Your NWC String Enter the NWC string copied from your Coinos wallet.
Complete Setup Test the connection to ensure everything works, and your wallet is ready to use!
The Flash Page Paywall feature lets you easily monetize your content by charging visitors to access specific pages. It's a straightforward solution to secure and generate revenue from premium content on your website.
Set a price and currency for accessing the page.
Payments are securely processed and sent directly to your wallet.
Embed the generated code snippet into your website or webpage to activate the paywall.
Follow the steps below to create your first page paywall:
Flash Payment Links offer a quick and convenient way to receive payments. These customizable URLs allow users to choose their preferred payment method and even set their own amount, making them ideal for flexible transactions.
We are working on integrating invoices directly into the payment links - look out for future releases.
Customizable Links: Define a default price that payers can adjust, ensuring flexibility for various payment scenarios.
Secure Transactions: Payments are directly routed to your selected wallet.
Easy Sharing: Share the link with others or embed it into buttons to streamline payment collection.
Follow the steps below to create your first payment link:
A Bitcoin wallet is essential to using Flash because it serves as the hub for receiving, storing, and managing your Bitcoin payments—much like a bank account does for traditional currencies. Here are the key reasons why a wallet is required:
Receive Payments When customers make payments using Bitcoin, the funds are directly sent to your wallet. Flash connects to your wallet to ensure smooth and secure transactions.
Flash is a Bitcoin Lightning payments gateway that ensures every payment is processed in a self-custodial and peer-to-peer (P2P) manner. Here's how it works: when you receive a payment through Flash, the funds are sent directly to your wallet, maintaining your full control and ownership.
To simplify operations, Flash's fees are handled automatically. Once a payment is completed, your wallet will initiate a small transaction to pay Flash its fee. This happens transparently in the background, ensuring you can focus entirely on growing your business without worrying about manual processes or hidden charges.
Our platform offers tools like Flashes, subscriptions, and public APIs to power your monetization needs. This documentation will guide you through integrating these features into your projects with ease, helping you create seamless and secure payment experiences while keeping full custody of your funds.




Click on the "Add New Product" button.
Fill in the following fields:
Name: The name of your product.
Price: The price of the product in your preferred currency or satoshis.
Category: Group your products for better organization (e.g., Beverages, Electronics).
Inventory: Optional – Track the available quantity.
More fields are available
Add one or multiple images to make your product visually appealing.
Save the product.
Each product will automatically generate:
A Checkout Page URL for direct sharing.
A Product Page URL for customers to view details and make purchases.
In the My Products dashboard, you can:
Edit product details.
Check inventory status.
View and copy checkout or product page URLs.
This gives you full control over your offerings, ensuring they’re always up-to-date.

Security and Ownership With a wallet, you retain full control and ownership of your Bitcoin. Flash doesn’t hold your funds, ensuring a decentralized and secure experience.
Transaction Management Your wallet provides a record of all incoming and outgoing transactions, enabling easy tracking and reconciliation of your payments.
Instant Access to Funds Bitcoin payments are processed instantly and are accessible in your wallet without intermediaries or delays.
Flash can only be used with wallets that support the Nostr Wallet Connect technology. The following wallets are currently compatible:
Click one of the tiles above to read specific instructions for each wallet. If you're using a different wallet, here are some generic instructions:
Make sure your wallet is NWC compatible Verify that the wallet supports Nostr Wallet Connect technology.
Find your NWC string on that wallet Locate the unique NWC string provided by your wallet for integration.
Paste it in Flash when creating a new wallet In the Flash’s wallet setup interface, create a new wallet and select the Nostr Wallet Connect options. Enter the NWC string to connect your wallet.
Verify with a small transaction Send a small amount of Bitcoin to ensure your wallet is correctly linked and transactions are processed smoothly.
Customizable Messaging: Set your call-to-action text, such as "Buy me a coffee," and personalize the widget to fit your needs.
Flexible Integration: Use a simple script to embed the widget into any HTML page or website builder.
Secure Payments: All payments are sent directly to your chosen wallet, ensuring a smooth and secure process.
Follow the steps below to create your first payment widget:
Flash Subscriptions allow you to easily manage recurring payments using Bitcoin Lightning. This section will guide you through everything you need to know to create and manage subscriptions effectively on your platform.
With Flash Subscriptions, you can:
Create and manage subscription plans: Learn how to set up subscription plans for your services or products, and generate a checkout page URL that users can visit to complete their subscription.
Pre-fill subscription forms: Simplify the user experience by passing user data, such as email, Nostr ID (npub), or a unique external_uuid, through URL parameters. This allows the subscription form to be pre-filled, reducing friction for your users.
Authenticate to interact with the API: Securely authenticate your application to interact with the subscription API. This will allow you to programmatically manage subscriptions, retrieve user details, and handle cancellations.
Utilize the subscription API: Access Flash’s API to check subscription statuses, manage cancellations, and retrieve important user information. The API enables seamless integration with your platform.
Receive real-time updates via webhooks: Stay informed of critical subscription events such as sign-ups, renewals, and payment failures by configuring webhooks that provide real-time notifications directly to your backend system.
In the following pages, you'll be guided through:
Creating a Subscription: Step-by-step instructions on how to set up your subscription plan and generate a checkout page URL.
Pre-filling User Data: How to pre-fill subscription forms using URL parameters, reducing the steps for your users.
Authentication: Learn how to authenticate to use the Flash Subscription API securely.
API Endpoints: Access API endpoints for managing subscriptions, retrieving user details, and handling cancellations.
Welcome to the Flash API documentation! Flash is a Bitcoin Lightning payments gateway enabling seamless subscription management, paywalls, and micropayments. This documentation will guide you through our public APIs, offering easy access to key functionalities to integrate with Flash. The API is designed with simplicity in mind to help developers quickly onboard and manage their integrations.
The Hosted Store combines all your products into a single online storefront, accessible via a unique URL. Customers can browse and purchase multiple products at once.
Shareable URL: Each business gets a unique store link.
Embeddable URL: Easily integrate the store into your website.
Customizable Layout: Products are automatically categorized based on your settings (e.g., Beverages, Electronics).
Add products to your My Products list.
Navigate to Products > My Store.
Copy the store URL or embed code provided.
You can customize the store’s appearance and functionality in future updates.
Checkouts are a set of versatile tools designed to enable flexible monetization for your content. Unlike traditional subscriptions, product sales, or e-commerce integrations, Flashes allow you to create unique payment solutions tailored to your specific needs. Each Flash operates independently, making them perfect for diverse use cases.
The Flash integration for Wix enables merchants to accept Bitcoin payments seamlessly through their online stores. Unlike WooCommerce, the Wix integration requires a custom setup due to Wix's requirements for custom apps. This guide explains the process and why a call with our team is necessary to get you up and running efficiently.
To ensure secure access, all requests to the Subscription API require an Authorization token. This token is unique for each subscription and must be included in the header of every API call. Here's how to authenticate your requests:
After you create a subscription in the Flash web app, a unique
Webhooks: Set up and manage webhook notifications for real-time updates on subscription activity.
The Flash integration for Wix provides a secure and user-friendly Bitcoin payment solution. Here's what it offers:
Accept Bitcoin payments directly in your Wix store.
Ensure non-custodial transactions for full control of your funds.
Provide your customers with cutting-edge payment options using the Bitcoin Lightning Network.
Due to Wix’s policies, custom app installations involve several steps that require access to specific tools, such as a Wix Partner Account. For this reason, our team will guide you through the installation process during a short 15-minute call.
Wix requires custom apps like Flash to be installed via a Partner Account, which ensures security and compliance. This process involves several technical steps that are not yet self-service, including:
Adding the Flash app to your Wix store through a Wix Partner Account.
Configuring the app settings to match your store’s requirements.
Connecting your Flash API key to enable Bitcoin payments.
Our team will handle these steps to ensure everything is set up correctly and quickly, saving you time and preventing potential errors.
Confirm Wix Store Requirements: Ensure you have a Wix store with a paid plan. Free or trial accounts are not eligible for custom app installations.
Book a Call with Flash: Schedule a 15-minute onboarding call with our team using this link.
Join the Call with Our Team: During the call, our team will:
Add the Flash app to your store via a Wix Partner Account.
Configure your store settings to integrate Flash seamlessly.
Guide you through connecting your Flash API key for Bitcoin payments.
Test and Enable Flash Payments: Once the setup is complete, we'll perform a quick test to ensure everything works as expected. After that, you can start accepting Bitcoin payments in your Wix store.
Streamlined Installation: Avoid the complexity of setting up a custom app on your own.
Expert Assistance: Get real-time support from our team to ensure your store is configured correctly.
Faster Setup: Complete the entire process in just 15 minutes.
If you have any questions before booking the call, feel free to contact us at [email protected].
Once set up, you’ll be equipped with the most advanced Bitcoin payment solution for Wix, enabling seamless and secure transactions for your customers.
Flash Wallet
Flash's dedicated mobile wallet, the easiest and most complete solution.
Coinos
A desktop-friendly wallet that is simple to set up and easy to use.
Alby
A premium service with advanced wallet functionality and a suite of Bitcoin tools.


Welcome to the Flash Subscription API! Flash makes it easy to manage and monetize recurring payments using Bitcoin Lightning. This is the starting point for creating your subscription plans, integrating APIs, and receiving real-time updates via webhooks.
Learn how to:
Create your first Subscription Plan: use the Flash web app to setup the parameters of your choice and get a checkout page url for you subscription plan.
Pre-Full User Details: you can customise the checkout page url by passing user information (email, npub and external user id - you can pass your backend user id as well)
Flash enables businesses to create and manage their products seamlessly, offering features like product pages, a full online store, and an integrated point-of-sale (PoS) system. These tools are designed to help you sell your products, manage transactions, and accept payments with minimal effort.
This guide covers everything you need to know about the Stores section, including how to:
Individual Product Pages: Each product you create gets its own checkout page with a unique URL.
Online Store: A public store combining all your products, available via a shareable URL or embeddable code for your website.
Point of Sale (PoS): A versatile PoS system for physical stores or quick manual sales, supporting both custom values and pre-configured products.
Customizable: Each Flash can be tailored to suit your content and audience.
Easy Integration: Simply copy and paste snippets into your HTML or use with website builders.
Secure Payments: All payments are processed directly to your wallet.
Flexible Use Cases: From one-time payments to dynamic paywalls, Flashes adapt to your needs.
Flashes empower you to monetize your content effectively while keeping the process simple for both you and your users.
For every API request, the token must be included in the Authorization header, formatted as follows:
Make sure to replace <Your-Subscription-API-Token> with the actual token you've obtained from the Flash web app.
Token Example
Here’s an example of how to structure your Authorization header in a typical API request:
If the token is missing or invalid, you will receive a 401 Unauthorized error.
For expired tokens, you will get a Token has expired message.
401 Unauthorized: Occurs when the token is invalid, missing, or expired.
Invalid Token Format: Ensure that the token is sent as Bearer <token> and is properly formatted.
Never share your Subscription API token publicly.
Make sure to use the correct subscription token for each individual subscription.
Seamless Integration: Add the button to any HTML page or website builder with an auto or manual snippet.
Customizable Options: Define a default price, currency, and optional redirect after payment.
Secure Payments: Transactions are sent directly to your selected wallet.
Follow the steps below to create your first payment button:
Flashes
Flexible, secure payment tools
Subscriptions
Manage recurring payments easily
Integrations
Seamless integration made simple
Authentication
Get your credentials
Subscriptions
Setup your subscriptions
Welcome to the Flash Integrations documentation! Flash simplifies Bitcoin payments for your online store and streaming platforms, providing seamless integration with popular e-commerce platforms. With our plugins and tools, you can easily enable non-custodial Bitcoin payments, empowering your customers to transact via the Lightning Network.
Whether you're a small business or a large-scale enterprise, Flash has you covered with robust, easy-to-use solutions.
Explore our growing list of supported platforms and learn how to integrate Flash with your preferred e-commerce solution. Each guide provides detailed, step-by-step instructions for setup and configuration.
Non-Custodial Payments: Retain full control over your funds with our non-custodial payment gateway.
Lightning Network Support: Leverage the power of instant and low-cost Bitcoin transactions.
Easy Integration: Our plugins and APIs are designed for quick setup and seamless functionality.
Transparent Fees: Pay only a small transaction fee with no hidden costs.
Need Help?
If you need assistance or have questions about Flash integrations, visit our Support Center or email us at [email protected].
The Flash Subscription allows you to streamline user experience by pre-filling subscription forms with data like email, Nostr ID (npub), and a unique identifier, external_uuid, when redirecting users to the subscription page. This saves users from re-entering details and enables you to integrate smoothly with your own user management systems.
When redirecting users to the Flash subscription page, you can pass relevant user information in the URL through a Base64-encoded JSON object. The system will automatically pre-fill the subscription form based on these values.
To ensure secure access, all requests to the Subscription API require an Authorization token. This token is unique for each subscription and must be included in the header of every API call. Here's how to authenticate your requests:
After you create a subscription in the Flash web app, a unique
The Flash plugin for WooCommerce allows merchants to accept Bitcoin payments through their online store effortlessly. This guide will walk you through the setup process, including downloading the plugin, configuring your API key, and enabling the payment gateway.
The first step in using Flash subscriptions is creating a subscription plan. Flash provides a simple interface for setting up subscription plans, which you can share with users via a checkout URL, or even embed directly into your website.
Here’s a quick overview of what you can do:
Create Subscription Plans: Set up multiple subscription tiers with different pricing options.
The Flash Video Paywall feature allows you to easily monetize video content by charging users after a predefined number of seconds. This innovative pay-as-you-watch model is designed to maximize revenue without requiring upfront payment for the entire video.
How it works:
You define a payment interval, e.g., every 60 seconds of video watching, the user is prompted to pay.
Authorization: Bearer <Your-Subscription-API-Token>POST https://api.paywithflash.com/v1/get_user_subscription_details
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cC...
Content-Type: application/x-www-form-urlencodedcurl -X POST https://api.paywithflash.com/v1/get_user_subscription_details \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cC..." \
-d "[email protected]&flash_id=12345"
email: The user's email address.
npub: The user's Nostr public key (Npub).
external_uuid: A unique identifier from your system to map users in your backend with Flash APIs. This value is not visible to users and is only used internally for identification.
is_verified: A boolean value indicating whether the user's email or Npub has already been verified.
If set to false, Flash will handle the verification process by either sending an email (for email addresses) or a Nostr DM (for Npubs) with a verification token.
If set to true, no additional verification steps are required, and the subscription process will continue seamlessly.
You can pass the following parameters by embedding them as a Base64-encoded JSON object in the params query string:
The resulting URL might look like this:
When Flash receives this URL, the system decodes the parameters and pre-populates the subscription form with the provided data.
Pre-Filled Fields: The user's email or Npub will be automatically filled into the form.
Verification:
If the user is not verified (i.e., is_verified = false), Flash will initiate the verification process by sending a verification token:
Email: The user will receive a token via email.
Npub: The user will receive a token via Nostr DM.
The user will then input the received token into the interface to verify their identity.
Note: The
external_uuidparameter is designed for developers to map their own user IDs with the Flash system, making it easy to track and manage users across platforms. This value is not shown to users.
Set Up the Redirect: Pass the user's email, Npub, and external UUID in the URL as described above.
Pre-Filled Form: The subscription page will pre-fill the user's details.
Verification (if required): If the user isn't verified, Flash sends a token via email or Nostr DM, which the user will input to complete verification.
Subscription Completed: Once verified, the user can complete their subscription without re-entering details.
{
"email": "[email protected]",
"npub": "npub123...",
"is_verified": false,
"external_uuid": "your-unique-user-id"
}https://app.paywithflash.com/subscription-page?flashId=459¶ms=<Base64-encoded-JSON>For every API request, the token must be included in the Authorization header, formatted as follows:
Make sure to replace <Your-Subscription-API-Token> with the actual token you've obtained from the Flash web app.
Token Example
Here’s an example of how to structure your Authorization header in a typical API request:
If the token is missing or invalid, you will receive a 401 Unauthorized error.
For expired tokens, you will get a Token has expired message.
401 Unauthorized: Occurs when the token is invalid, missing, or expired.
Invalid Token Format: Ensure that the token is sent as Bearer <token> and is properly formatted.
Never share your Subscription API token publicly.
Make sure to use the correct subscription token for each individual subscription.
The Flash plugin integrates directly with WooCommerce to provide a secure and user-friendly Bitcoin payment solution. With this plugin, you can:
Accept Bitcoin payments directly in your store.
Ensure non-custodial transactions with full control of your funds.
Enhance your store’s payment options with a cutting-edge Lightning Network solution.
Download the Plugin: Access the Flash plugin from your dashboard and download the zip file.
Install the Plugin on WooCommerce: Upload the downloaded plugin file to your WooCommerce store and activate it.
Configure Your API Key: Generate and input your unique API key to connect your store with the Flash payment gateway.
Enable Flash Payments: Adjust your WooCommerce payment settings to activate the "Flash - Pay in Bitcoin" option.
Embed Checkout Pages: Use the subscription plan URL to redirect users to the payment page or embed it on your platform for a seamless experience.
Manage Payments: Track recurring payments and stay updated with webhook notifications.
Once your subscription is created, you will get:
A checkout URL to share or embed.
A secret key to authenticate webhook messages for real-time updates.
After creating your subscription, you’ll be ready to:
Use the Flash Subscription API: Retrieve subscription details, manage cancellations, and more.
Set up Webhook Integration: Stay notified about key subscription events like sign-ups, renewals, and payment failures by integrating with our webhook system.
Prefill user detail: Redirect users with more invormation to improve user experience
Authenticate: Learn how to authenticate with the Subscription API.
Endpoints: Review available API endpoints for managing subscriptions.
Webhooks: Get real-time notifications for subscription events.
Once you have created your subscription, you can easily embed the checkout page or redirect users to it. This provides a seamless experience for users to subscribe to your service without needing to sign in beforehand. Simply copy the generated checkout URL and use it as needed.
Users only pay for the content they watch, providing a flexible experience.
Integrate the video paywall by embedding the code snippet generated in the Flash dashboard.
Follow the steps below to create your first video paywall:
Easily switch between manual and product-based transactions
For quick transactions where you manually input the amount:
Navigate to Products > My PoS.
Select the "Point of Sale" tab.
Use the calculator to enter a custom amount.
Generate an invoice to process the payment.
For businesses selling pre-configured products:
Navigate to Products > My PoS.
Select the "Products" tab.
Choose products from the displayed list to add to the current order.
Payment Links
Create shareable URLs that allow users to pay easily by selecting their preferred payment method and amount.
Donation Widgets
Add a floating, customizable call-to-action on your website to encourage donations or user contributions.
Page Paywalls
Secure content behind a paywall, requiring users to pay for access to premium webpages. Ideal for articles, guides, or any content that needs restricted access.
Video Paywalls
Monetize video content by charging viewers based on watch time. Perfect for providing users with a pay-as-you-watch experience.
Payment Buttons
Embed buttons on your site to trigger payments through a secure modal or redirect users post-payment.

The Flash integration for Shopify enables merchants to accept Bitcoin payments seamlessly through their online stores. Unlike WooCommerce, the Shopify integration requires a custom setup due to Shopify's requirements for custom apps. This guide explains the process and why a call with our team is necessary to get you up and running efficiently.
Authorization: Bearer <Your-Subscription-API-Token>POST https://api.paywithflash.com/v1/get_user_subscription_details
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cC...
Content-Type: application/x-www-form-urlencodedcurl -X POST https://api.paywithflash.com/v1/get_user_subscription_details \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cC..." \
-d "[email protected]&flash_id=12345"The Flash integration for Shopify provides a secure and user-friendly Bitcoin payment solution. Here's what it offers:
Accept Bitcoin payments directly in your Shopify store.
Ensure non-custodial transactions for full control of your funds.
Provide your customers with cutting-edge payment options using the Bitcoin Lightning Network.
Due to Shopify’s policies, custom app installations involve several steps that require access to specific tools, such as a Shopify Partner Account. For this reason, our team will guide you through the installation process during a short 15-minute call.
Shopify requires custom apps like Flash to be installed via a Partner Account, which ensures security and compliance. This process involves several technical steps that are not yet self-service, including:
Adding the Flash app to your Shopify store through a Shopify Partner Account.
Configuring the app settings to match your store’s requirements.
Connecting your Flash API key to enable Bitcoin payments.
Our team will handle these steps to ensure everything is set up correctly and quickly, saving you time and preventing potential errors.
Confirm Shopify Store Requirements: Ensure you have a Shopify store with a paid plan. Free or trial accounts are not eligible for custom app installations.
Book a Call with Flash: Schedule a 15-minute onboarding call with our team using this link.
Join the Call with Our Team: During the call, our team will:
Add the Flash app to your store via a Shopify Partner Account.
Configure your store settings to integrate Flash seamlessly.
Guide you through connecting your Flash API key for Bitcoin payments.
Test and Enable Flash Payments: Once the setup is complete, we'll perform a quick test to ensure everything works as expected. After that, you can start accepting Bitcoin payments in your Shopify store.
Streamlined Installation: Avoid the complexity of setting up a custom app on your own.
Expert Assistance: Get real-time support from our team to ensure your store is configured correctly.
Faster Setup: Complete the entire process in just 15 minutes.
If you have any questions before booking the call, feel free to contact us at [email protected].
Once set up, you’ll be equipped with the most advanced Bitcoin payment solution for Shopify, enabling seamless and secure transactions for your customers.








Generate an invoice with a breakdown of selected items.

Email of the user
Nostr npub identifier of the user
External UUID for identifying the user
Unique Flash ID associated with the user
Successfully retrieved user subscription details
Missing required parameters or invalid request
Unauthorized or invalid token
Internal server error
Email of the user
Nostr npub identifier of the user
External UUID for identifying the user
Unique Flash ID associated with the user
Subscription successfully canceled
Unauthorized or invalid token
No subscription found for the given parameters
Internal server error
POST /v1/get_user_subscription_details HTTP/1.1
Host: api.paywithflash.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/x-www-form-urlencoded
Accept: */*
Content-Length: 71
"email='text'&npub='text'&external_uuid='text'&flash_id='text'"POST /v1/cancel_user_subscription HTTP/1.1
Host: api.paywithflash.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/x-www-form-urlencoded
Accept: */*
Content-Length: 71
"email='text'&npub='text'&external_uuid='text'&flash_id='text'"
{
"membership": {},
"transactions": [
{}
]
}{
"success": true
}

Retrieves subscription details and transaction history for a user
JWT token signed with the Flash secret key
The Flash ID for the platform
User's email address (one of email, npub, or external_uuid required)
User's Nostr public key in npub format (one of email, npub, or external_uuid required)
External UUID for the user (one of email, npub, or external_uuid required)
Successful response
Bad request
Unauthorized
Forbidden
Not found
Internal server error
Cancels a user's active subscription
JWT token signed with the Flash secret key
The Flash ID for the platform
User's email address (one of email, npub, or external_uuid required)
User's Nostr public key in npub format (one of email, npub, or external_uuid required)
External UUID for the user (one of email, npub, or external_uuid required)
Successful cancellation
Bad request
Unauthorized
Not found
Internal server error
{
"membership": {
"user_public_key": "text",
"is_paid": true,
"membership_start_date": "text",
"next_payment_date": "text",
"status": "text",
"external_uuid": "text"
},
"transactions": [
{
"id": 1,
"from_public_key": "text",
"to_public_key": "text",
"transaction_date": "text",
"amount_in_sats": 1,
"amount_in_currency": 1,
"currency": "text",
"bitcoin_price": 1,
"flash_id": "text",
"flash_name": "text",
"flash_type": "text",
"to_wallet_id": 1,
"to_user_wallet_name": "text",
"from_wallet_id": 1,
"from_user_wallet_name": "text",
"lnurl": "text"
}
]
}{
"success": true
}POST /v1/get_user_subscription_details HTTP/1.1
Host: api.paywithflash.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/x-www-form-urlencoded
Accept: */*
Content-Length: 71
"flash_id='text'&email='text'&npub='text'&external_uuid='text'"POST /v1/cancel_user_subscription HTTP/1.1
Host: api.paywithflash.com
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/x-www-form-urlencoded
Accept: */*
Content-Length: 71
"flash_id='text'&email='text'&npub='text'&external_uuid='text'"Webhook Integration Guide for Subscription Management
This guide is intended for developers looking to integrate real-time subscription event notifications into their applications. With our webhook system, you’ll receive automated POST requests to your designated URL for events like new sign-ups, renewals, and payment failures.
A webhook allows our system to send real-time updates 📡 to your application. We’ll POST a JSON payload to your specified endpoint whenever a relevant subscription event occurs.
You can set up a webhook URL in the Flash web app either while creating a new subscription or by editing an existing subscription:
When creating a new subscription:
Head over to New Subs > Create a Subscription Plan
Make sure to click on the “Use Advanced Webhook Features” checkbox to make the Webhook Url field appear
Input your
To receive webhook notifications, set up a POST endpoint in your application:
Ensure it accepts JSON payloads.
Process the data based on the event type and take appropriate actions.
Security Tip: Always use HTTPS to secure webhook transmissions.
Your webhook endpoint should respond with a 200 OK status to acknowledge receipt of the event. If no response or an error is received, we may retry the notification.
The system triggers the following events, each sending a POST request with event data to your webhook:
The data sent to your webhook URL will be structured as a JSON object containing two primary fields: eventType and data. The eventType field indicates the type of event, while the data field contains event-specific information.
All webhooks include a JWT token in the Authorization header, allowing you to verify that the event is coming from Flash. You can decode and verify this token using the subscription key provided in the web app.
Example token:
Token Expiration: The token is valid for 1 hour.
To verify the token, decode it using your subscription key and the HS256 algorithm.
Your webhook should always respond with a 200 OK status after processing the event. Failure to do so may cause the system to retry the notification.
Idempotency: Ensure that your webhook handler can process the same event more than once without causing errors or duplicate actions.
Logging: Implement logging for all webhook events to make troubleshooting easier.
Can I set up multiple webhook URLs?
By integrating our webhook system, you can stay updated on key subscription events in real time, helping automate and optimize your processes. Feel free to contact our developer support team if you need any help.
Assuming your webhook URL is https://webhook , you can refer to the following code:
After creating the Subscription, you will receive a url with the subscription and the subscription key. You can use this key to decode and verify the JWT token that comes with our event (see guide below).
When you have already created a subscription:
Head over to My Subscriptions
Select the subscription you want to add webhooks for
Click on “Edit Subscription”
Fill in/modify the Webhook Url field
The subscription key is also visible in this screen and can be used to decode and verify the JWT token that comes with our event (see guide below).
name: The user's name.
email: The user's email address.
about: A brief description of the user.
picture_url: The URL to the user's profile picture.
user_plan: The subscription plan the user has signed up for.
user_plan_id: The subscription plan id the user has signed up for.
Event-Specific Fields:
signup_date: The date the user signed up (only for user_signed_up).
next_payment_date: The next payment date for the subscription (only for renewal_successful).
failed_payment_date: The date of the failed payment (only for renewal_failed).
transaction_id: The ID of the transaction (varies by event type).
transaction_amount: The payment amount of the transaction(all same)
transaction_currency: The currency of the transaction(all same)
transaction_date: The date of the transaction (varies by event type).
Webhook Integration Guide for Subscription Management
This guide is intended for developers looking to integrate real-time subscription event notifications into their applications. With our webhook system, you’ll receive automated POST requests to your designated URL for events like new sign-ups, renewals, and payment failures.
A webhook allows our system to send real-time updates 📡 to your application. We’ll POST a JSON payload to your specified endpoint whenever a relevant subscription event occurs.
You can set up a webhook URL in the Flash web app either while creating a new subscription or by editing an existing subscription:
When creating a new subscription:
Head over to New Subs > Create a Subscription Plan
Make sure to click on the “Use Advanced Webhook Features” checkbox to make the Webhook Url field appear
Input your
To receive webhook notifications, set up a POST endpoint in your application:
Ensure it accepts JSON payloads.
Process the data based on the event type and take appropriate actions.
Security Tip: Always use HTTPS to secure webhook transmissions.
Your webhook endpoint should respond with a 200 OK status to acknowledge receipt of the event. If no response or an error is received, we may retry the notification.
The system triggers the following events, each sending a POST request with event data to your webhook:
The data sent to your webhook URL will be structured as a JSON object containing two primary fields: eventType and data. The eventType field indicates the type of event, while the data field contains event-specific information.
All webhooks include a JWT token in the Authorization header, allowing you to verify that the event is coming from Flash. You can decode and verify this token using the subscription key provided in the web app.
Example token:
Token Expiration: The token is valid for 1 hour.
To verify the token, decode it using your subscription key and the HS256 algorithm.
Your webhook should always respond with a 200 OK status after processing the event. Failure to do so may cause the system to retry the notification.
Idempotency: Ensure that your webhook handler can process the same event more than once without causing errors or duplicate actions.
Logging: Implement logging for all webhook events to make troubleshooting easier.
Can I set up multiple webhook URLs?
By integrating our webhook system, you can stay updated on key subscription events in real time, helping automate and optimize your processes. Feel free to contact our developer support team if you need any help.
Assuming your webhook URL is https://webhook , you can refer to the following code:
{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "23",
"signup_date": "2024-02-15",
"next_payment_date": "2024-03-15",
"failed_payment_date": "",
"transaction_id": "654",
"transaction_amount": "100",
"transaction_currency": "Satoshis"
"transaction_date": "2024-02-15"
}
}{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "24"
"signup_date": "2024-02-15",
"next_payment_date": "2024-04-15",
"failed_payment_date": "",
"transaction_id": "837",
"transaction_amount": "100",
"transaction_currency": "Satoshis",
"transaction_date": "2024-03-15"
}
}{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "67",
"signup_date": "2024-02-15",
"next_payment_date": "",
"failed_payment_date": "2024-03-15",
"transaction_id": "-1",
"transaction_amount": "100",
"transaction_currency": "Satoshis",
"transaction_date": ""
}
}{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "67",
"signup_date": "2024-02-15",
"next_payment_date": "",
"failed_payment_date": "2024-03-15",
"transaction_id": "-1",
"transaction_amount": "100",
"transaction_currency": "Satoshis",
"transaction_date": ""
}
}{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "67",
"signup_date": "2024-02-15",
"next_payment_date": "",
"failed_payment_date": "2024-03-15",
"transaction_id": "-1",
"transaction_amount": "100",
"transaction_currency": "Satoshis",
"transaction_date": ""
}
}{
"version": "1.0",
"eventType": {
"id": "1",
"name": "user_signed_up"
},
"user_public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"exp": "2024-05-01T08:48:38Z"
}const jwt = require('jsonwebtoken');
app.post('/webhook', (req, res) => {
const data = req.body; // Extract JSON data from the request
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
// Verify and decode the JWT token
const secret = 'your_secret_key';
jwt.verify(token, secret, (err, decodedToken) => {
if (err) {
return res.status(401).json({ error: 'Invalid token' });
}
const { version, eventType, user_public_key } = decodedToken;
// Process the data as needed
console.log('User public key:', user_public_key);
console.log('Event Type:', eventType);
});
// Access fields from the JSON payload
const userPublicKey = data.data.public_key;
const userName = data.data.name;
const userEmail = data.data.email;
// Process the data...
res.json({ ok: true });
});
from flask import request, jsonify
import jwt
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.get_json()
auth_header = request.headers.get('Authorization')
token = auth_header.split(" ")[1] if auth_header else None
if not token:
return jsonify({'error': 'No token provided'}), 401
secret = 'your_secret_key'
try:
decoded_token = jwt.decode(token, secret, algorithms=['HS256'])
version = decoded_token.get('version')
event_type = decoded_token.get('eventType')
user_public_key = decoded_token.get('user_public_key')
print(f"User public key: {user_public_key}")
print(f"Event Type: {event_type}")
except jwt.ExpiredSignatureError:
return jsonify({'error': 'Token has expired'}), 401
except jwt.InvalidTokenError:
return jsonify({'error': 'Invalid token'}), 401
user_public_key = data.get('data').get('public_key')
user_name = data.get('data').get('name')
user_email = data.get('data').get('email')
return jsonify({'ok': True})
require 'json'
require 'jwt'
post '/webhook' do
data = JSON.parse(request.body.read)
auth_header = request.env['HTTP_AUTHORIZATION']
token = auth_header.split(' ')[1] if auth_header
halt 401, { error: 'No token provided' }.to_json unless token
secret = 'your_secret_key'
begin
decoded_token = JWT.decode(token, secret, true, algorithm: 'HS256')[0]
user_public_key = decoded_token['user_public_key']
event_type = decoded_token['eventType']
puts "User public key: #{user_public_key}"
puts "Event Type: #{event_type}"
rescue JWT::ExpiredSignature
halt 401, { error: 'Token has expired' }.to_json
rescue JWT::DecodeError
halt 401, { error: 'Invalid token' }.to_json
end
user_public_key = data['data']['public_key']
user_name = data['data']['name']
user_email = data['data']['email']
{ ok: true }.to_json
end
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import io.jsonwebtoken.*;
import java.util.Map;
@RestController
public class WebhookController {
@PostMapping("/webhook")
public ResponseEntity<?> handleWebhook(@RequestBody Map<String, Object> payload,
@RequestHeader("Authorization") String authHeader) {
String token = authHeader != null ? authHeader.split(" ")[1] : null;
if (token == null) {
return ResponseEntity.status(401).body(Map.of("error", "No token provided"));
}
String secret = "your_secret_key";
try {
Jws<Claims> decodedToken = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token);
String version = (String) decodedToken.getBody().get("version");
Map<String, Object> eventType = (Map<String, Object>) decodedToken.getBody().get("eventType");
String userPublicKey = (String) decodedToken.getBody().get("user_public_key");
System.out.println("User public key: " + userPublicKey);
System.out.println("Event Type: " + eventType);
} catch (ExpiredJwtException e) {
return ResponseEntity.status(401).body(Map.of("error", "Token has expired"));
} catch (JwtException e) {
return ResponseEntity.status(401).body(Map.of("error", "Invalid token"));
}
Map<String, Object> data = (Map<String, Object>) payload.get("data");
String userPublicKey = (String) data.get("public_key");
String userName = (String) data.get("name");
String userEmail = (String) data.get("email");
return ResponseEntity.ok(Map.of("ok", true));
}
}
require 'vendor/autoload.php'; // Include JWT library (e.g., firebase/php-jwt)
use \Firebase\JWT\JWT;
$secret = 'your_secret_key';
$data = json_decode(file_get_contents('php://input'), true);
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? null;
if ($authHeader) {
$token = explode(' ', $authHeader)[1];
} else {
http_response_code(401);
echo json_encode(['error' => 'No token provided']);
exit;
}
try {
$decodedToken = JWT::decode($token, $secret, ['HS256']);
$decodedArray = (array) $decodedToken;
$userPublicKey = $decodedArray['user_public_key'];
$eventType = $decodedArray['eventType'];
echo "User public key: $userPublicKey\n";
echo "Event Type: $eventType\n";
} catch (Exception $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid token']);
exit;
}
$userPublicKey = $data['data']['public_key'] ?? null;
$userName = $data['data']['name'] ?? null;
$userEmail = $data['data']['email'] ?? null;
echo json_encode(['ok' => true]);


After creating the Subscription, you will receive a url with the subscription and the subscription key. You can use this key to decode and verify the JWT token that comes with our event (see guide below).
When you have already created a subscription:
Head over to My Subscriptions
Select the subscription you want to add webhooks for
Click on “Edit Subscription”
Fill in/modify the Webhook Url field
The subscription key is also visible in this screen and can be used to decode and verify the JWT token that comes with our event (see guide below).
name: The user's name.
email: The user's email address.
about: A brief description of the user.
picture_url: The URL to the user's profile picture.
user_plan: The subscription plan the user has signed up for.
user_plan_id: The subscription plan id the user has signed up for.
Event-Specific Fields:
signup_date: The date the user signed up (only for user_signed_up).
next_payment_date: The next payment date for the subscription (only for renewal_successful).
failed_payment_date: The date of the failed payment (only for renewal_failed).
transaction_id: The ID of the transaction (varies by event type).
transaction_amount: The payment amount of the transaction(all same)
transaction_currency: The currency of the transaction(all same)
transaction_date: The date of the transaction (varies by event type).
{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "23",
"signup_date": "2024-02-15",
"next_payment_date": "2024-03-15",
"failed_payment_date": "",
"transaction_id": "654",
"transaction_amount": "100",
"transaction_currency": "Satoshis"
"transaction_date": "2024-02-15"
}
}{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "24"
"signup_date": "2024-02-15",
"next_payment_date": "2024-04-15",
"failed_payment_date": "",
"transaction_id": "837",
"transaction_amount": "100",
"transaction_currency": "Satoshis",
"transaction_date": "2024-03-15"
}
}{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "67",
"signup_date": "2024-02-15",
"next_payment_date": "",
"failed_payment_date": "2024-03-15",
"transaction_id": "-1",
"transaction_amount": "100",
"transaction_currency": "Satoshis",
"transaction_date": ""
}
}{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "67",
"signup_date": "2024-02-15",
"next_payment_date": "",
"failed_payment_date": "2024-03-15",
"transaction_id": "-1",
"transaction_amount": "100",
"transaction_currency": "Satoshis",
"transaction_date": ""
}
}{
"data": {
"public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"external_uuid": "adf8cab9-add3-400d-b83c-9b68cfb6be8d",
"name": "Jane Doe",
"email": "[email protected]",
"about": "Enthusiast of digital art",
"picture_url": "<https://example.com/jane.jpg>",
"user_plan": "Premium",
"user_plan_id": "67",
"signup_date": "2024-02-15",
"next_payment_date": "",
"failed_payment_date": "2024-03-15",
"transaction_id": "-1",
"transaction_amount": "100",
"transaction_currency": "Satoshis",
"transaction_date": ""
}
}{
"version": "1.0",
"eventType": {
"id": "1",
"name": "user_signed_up"
},
"user_public_key": "55a12716a6c4e8c95fc83dc046c3ea2209d3e3a1b87b15c48ef562b5a8599ed8",
"exp": "2024-05-01T08:48:38Z"
}const jwt = require('jsonwebtoken');
app.post('/webhook', (req, res) => {
const data = req.body; // Extract JSON data from the request
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
// Verify and decode the JWT token
const secret = 'your_secret_key';
jwt.verify(token, secret, (err, decodedToken) => {
if (err) {
return res.status(401).json({ error: 'Invalid token' });
}
const { version, eventType, user_public_key } = decodedToken;
// Process the data as needed
console.log('User public key:', user_public_key);
console.log('Event Type:', eventType);
});
// Access fields from the JSON payload
const userPublicKey = data.data.public_key;
const userName = data.data.name;
const userEmail = data.data.email;
// Process the data...
res.json({ ok: true });
});
from flask import request, jsonify
import jwt
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.get_json()
auth_header = request.headers.get('Authorization')
token = auth_header.split(" ")[1] if auth_header else None
if not token:
return jsonify({'error': 'No token provided'}), 401
secret = 'your_secret_key'
try:
decoded_token = jwt.decode(token, secret, algorithms=['HS256'])
version = decoded_token.get('version')
event_type = decoded_token.get('eventType')
user_public_key = decoded_token.get('user_public_key')
print(f"User public key: {user_public_key}")
print(f"Event Type: {event_type}")
except jwt.ExpiredSignatureError:
return jsonify({'error': 'Token has expired'}), 401
except jwt.InvalidTokenError:
return jsonify({'error': 'Invalid token'}), 401
user_public_key = data.get('data').get('public_key')
user_name = data.get('data').get('name')
user_email = data.get('data').get('email')
return jsonify({'ok': True})
require 'json'
require 'jwt'
post '/webhook' do
data = JSON.parse(request.body.read)
auth_header = request.env['HTTP_AUTHORIZATION']
token = auth_header.split(' ')[1] if auth_header
halt 401, { error: 'No token provided' }.to_json unless token
secret = 'your_secret_key'
begin
decoded_token = JWT.decode(token, secret, true, algorithm: 'HS256')[0]
user_public_key = decoded_token['user_public_key']
event_type = decoded_token['eventType']
puts "User public key: #{user_public_key}"
puts "Event Type: #{event_type}"
rescue JWT::ExpiredSignature
halt 401, { error: 'Token has expired' }.to_json
rescue JWT::DecodeError
halt 401, { error: 'Invalid token' }.to_json
end
user_public_key = data['data']['public_key']
user_name = data['data']['name']
user_email = data['data']['email']
{ ok: true }.to_json
end
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import io.jsonwebtoken.*;
import java.util.Map;
@RestController
public class WebhookController {
@PostMapping("/webhook")
public ResponseEntity<?> handleWebhook(@RequestBody Map<String, Object> payload,
@RequestHeader("Authorization") String authHeader) {
String token = authHeader != null ? authHeader.split(" ")[1] : null;
if (token == null) {
return ResponseEntity.status(401).body(Map.of("error", "No token provided"));
}
String secret = "your_secret_key";
try {
Jws<Claims> decodedToken = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token);
String version = (String) decodedToken.getBody().get("version");
Map<String, Object> eventType = (Map<String, Object>) decodedToken.getBody().get("eventType");
String userPublicKey = (String) decodedToken.getBody().get("user_public_key");
System.out.println("User public key: " + userPublicKey);
System.out.println("Event Type: " + eventType);
} catch (ExpiredJwtException e) {
return ResponseEntity.status(401).body(Map.of("error", "Token has expired"));
} catch (JwtException e) {
return ResponseEntity.status(401).body(Map.of("error", "Invalid token"));
}
Map<String, Object> data = (Map<String, Object>) payload.get("data");
String userPublicKey = (String) data.get("public_key");
String userName = (String) data.get("name");
String userEmail = (String) data.get("email");
return ResponseEntity.ok(Map.of("ok", true));
}
}
require 'vendor/autoload.php'; // Include JWT library (e.g., firebase/php-jwt)
use \Firebase\JWT\JWT;
$secret = 'your_secret_key';
$data = json_decode(file_get_contents('php://input'), true);
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? null;
if ($authHeader) {
$token = explode(' ', $authHeader)[1];
} else {
http_response_code(401);
echo json_encode(['error' => 'No token provided']);
exit;
}
try {
$decodedToken = JWT::decode($token, $secret, ['HS256']);
$decodedArray = (array) $decodedToken;
$userPublicKey = $decodedArray['user_public_key'];
$eventType = $decodedArray['eventType'];
echo "User public key: $userPublicKey\n";
echo "Event Type: $eventType\n";
} catch (Exception $e) {
http_response_code(401);
echo json_encode(['error' => 'Invalid token']);
exit;
}
$userPublicKey = $data['data']['public_key'] ?? null;
$userName = $data['data']['name'] ?? null;
$userEmail = $data['data']['email'] ?? null;
echo json_encode(['ok' => true]);

