Developer guide

Flutter licensing integration

From payment selection to an offline-verifiable Ed25519 certificate. This guide walks through the complete AtomCyou integration.

Overview

One payment, one trusted certificate

AtomCyou issues certificates compatible with flutter_licensing. Your application embeds only the public key. The private signing key remains encrypted in D1 and is decrypted in memory only while issuing a license.

1. Customer pays

Your app opens CorePort directly with the selected plan.

2. Atom verifies

A signed webhook confirms customer, amount, currency, and plan.

3. App imports

The certificate is verified locally and works offline.

Step 1

Create and upload a signing key

Generate an RFC 8410 Ed25519 key pair, then upload the private signing key in the AtomCyou project portal. AtomCyou encrypts it before storing it and decrypts it in memory only while issuing a license.

Terminalshell
openssl genpkey -algorithm ED25519 -out license-private.pem
openssl pkey -in license-private.pem -pubout -out license-public.pem

The private key is shown only once in the portal. Save it securely before leaving that screen. After upload, AtomCyou never reveals or returns it. Never bundle, log, email, or commit it. When rotating keys, release the new public key in your app before issuing certificates with it.

Step 2

Add the public key to Flutter

Download the public key from your AtomCyou project and bundle it as an application asset. The key ID in the asset registry must match the certificate’s key_id.

pubspec.yaml
flutter:
  assets:
    - assets/license_keys/key-2026-08-30.pub
Dart
final keys = LicenseKeyRegistry();
await keys.addAsset('key-2026-08-30');

Step 3

Configure customer plans

Every tier has separate human-facing and program-facing identifiers. This lets your UI use natural language without coupling application code to it.

Display name
My premium plan

Shown to customers. Unicode and spaces are welcome.

Program ID
moj-superplan

Stable, unique within the project, and sent as CorePort custom field planid.

Step 4

Open CorePort with the AtomCyou webhook

Your application calls CorePort directly. In CorePort or CorePass, set the webhook URL to https://atom.cyou/wh/{project} and put the program-facing plan ID in Additional Webhook Data. AtomCyou uses CorePort’s signed customerCoreId field as the license owner; do not duplicate it in custom data.

Additional Webhook Data

{"planid": "moj-superplan", "customerid": "id1234", "deviceid": "device-123", "product": "onl.tone.app"}

planid and at least one identity are required. Use CorePort’s customerCoreId, custom customerid, high-entropy deviceid, or both customer and device. product is signed into the certificate. If the project has an Application ID rule, it is required and must match exactly; otherwise it is optional and defaults to the project product. Device-only apps are supported; AtomCyou stores and exposes only its SHA-256 hash.

GETCorePort payment link
https://coreport.net/link
  ?id=YOUR_MERCHANT_CORE_ID
  &amount=12.99
  &currency=EUR
  &wh=https://atom.cyou/wh/my-project
  &wh-data={"planid":"moj-superplan"}
  &rd=https://your-app.example/payment/complete

Never trust the browser redirect

A redirect only means the customer returned from checkout. Poll the customer license endpoint; AtomCyou issues a new certificate only after CorePort’s detached signed webhook passes plan, amount, currency, slippage, capacity, and replay checks.

Step 5

Synchronize the certificate

Synchronize active certificates by Core ID or customer ID. The owner is signed as id; only SHA-256 of the optional secure installation ID is signed as device_id_hash. The raw device ID is not stored or returned.

GET https://atom.cyou/api/v1/my-project/sync/{coreid-or-customerid}

AtomCyou verifies the signed payment, customer, plan, amount, currency, slippage, and capacity.

Flutter verifies product, key ID, time bounds, and Ed25519 signature locally.

Reference

Public API endpoints

GET/api/v1/{project}/licenses/{customerId}

Retrieve the customer’s current license certificates.

GET/api/v1/{project}/sync/{customerId}

Synchronize active customer certificates.

GET/api/v1/{project}/keys

Retrieve the project’s current public trust key.

POST/wh/{project}

CorePort customer-payment webhook. Do not call from the app.

Production checklist

  • Bundle trusted public keys in the released app.
  • Use an opaque, unguessable customer ID.
  • Never grant access from redirect parameters.
  • Ship new public keys before rotating issuance.