Skip to main content
Every integrator on the Zeam platform operates through a registered application. This guide walks you through the full lifecycle: creating the application, moving it through approval, managing credentials, and wiring up webhooks.

Prerequisites

  • A OAuth bearer token (Authorization: Bearer $TOKEN) for all requests below. See OAuth end-users.
  • Your association ID (UUID). Retrieve it with GET /v1/business/association/all.

1. Register your application

Registration generates a Stellar keypair, provisions authentication credentials, registers for Connect access, and returns one-time-visible credentials. Store them immediately — they cannot be retrieved again.
1

Submit the registration request

curl -s -X POST https://api.zeam.money/gw/v1/application \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "associationId": "your-association-uuid",
    "applicationName": "My Payment Service",
    "webhookUrl": "https://your-domain.com/webhooks/zeam",
    "webhookMethod": "POST"
  }' | jq
The Stellar keypair, classification, and environment are generated server-side. You only need to supply associationId and applicationName.
2

Capture the one-time credentials

The response contains credentials that are shown exactly once:
{
  "data": {
    "application": {
      "id": "app-uuid",
      "applicationName": "My Payment Service",
      "status": "draft",
      "activated": true,
      "publicKey": "GABC...GENERATED",
      "environment": "sandbox"  // Zeam-assigned field: "sandbox" or "production"
    },
    "stellar": {
      "publicKey": "GABC...GENERATED",
      "secret": "SABC...ONE_TIME_VISIBLE",
      "vaultId": "vault-uuid"
    },
    "apiKey": {
      "keyId": "ak_abc123",
      "secret": "ONE_TIME_VISIBLE_SECRET",
      "last4": "cret"
    },
    "connectSecret": "ONE_TIME_VISIBLE",
    "webhookSecret": {
      "webhookId": "webhook-uuid",
      "secret": "ONE_TIME_VISIBLE_SIGNING_KEY",
      "last4": "key1"
    },
    "integratorId": "integrator-uuid"
  },
  "status": 201,
  "message": "Created"
}
Store every secret in your secret manager (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault) before proceeding. If you lose them, you must rotate via the credential and webhook-secret rotation endpoints.
3

Authenticate with Ed25519

Use your new Stellar keypair to authenticate via Ed25519 and start making API calls.

Using the Go SDK

import "github.com/ZeamMoney/zeam-sdk-go/recipes"

result, err := recipes.RegisterApplication(ctx, client, recipes.RegisterAppInput{
    Session: businessSession,
    Payload: registrationPayload,
    CaptureOneTimeSecrets: func(ctx context.Context, s recipes.OneTimeSecrets) error {
        // Store these in your secret manager NOW.
        return storeInVault(ctx, s)
    },
})
// The SDK zeros the secrets in memory after this callback returns.

2. Application lifecycle

After registration, your application starts in draft status and moves through a gated lifecycle:

Submit for review

When your application is ready, submit it for approval. The status changes from draft to pending_approval.
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/submit \
  -H "Authorization: Bearer $TOKEN" | jq

Approve

An authorised reviewer approves the application. A two-person rule applies — the approver must differ from the user who submitted the application.
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/approve \
  -H "Authorization: Bearer $TOKEN" | jq

Reject

If the application does not meet requirements, the reviewer rejects it with an optional reason:
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/reject \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"reason": "Missing settlement account configuration"}' | jq

Suspend and resume

An approved application can be suspended temporarily (e.g. for compliance review) and resumed later:
# Suspend
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/suspend \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"reason": "Compliance review pending"}' | jq

# Resume
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/resume \
  -H "Authorization: Bearer $TOKEN" | jq

Revoke

Revocation is terminal — the application can never be reactivated. Use this for permanent offboarding.
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/revoke \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"reason": "Contract terminated"}' | jq
Every lifecycle transition returns the updated application state and is recorded in the audit trail.

3. Check application status

Get a single application

curl -s https://api.zeam.money/gw/v1/application/$APP_ID \
  -H "Authorization: Bearer $TOKEN" | jq '.data'
Response:
{
  "id": "app-uuid",
  "associationId": "assoc-uuid",
  "applicationName": "My Payment Service",
  "classificationCode": "PARTNER_PSP",
  "publicKey": "GABC...",
  "environment": "sandbox",  // Zeam-assigned: reflects Sandbox mode or production access
  "status": "approved",
  "activated": true,
  "createdAt": "2026-05-10T12:00:00Z",
  "updatedAt": "2026-05-10T14:30:00Z"
}

List applications for an association

curl -s "https://api.zeam.money/gw/v1/applications/$ASSOCIATION_ID?status=approved" \
  -H "Authorization: Bearer $TOKEN" | jq '.data'
The optional status query parameter filters by lifecycle state: draft, pending_approval, approved, suspended, revoked, rejected.

Lookup by Stellar public key

curl -s "https://api.zeam.money/gw/v1/application/lookup?publicKey=GABC...KEY" \
  -H "Authorization: Bearer $TOKEN" | jq '.data'

4. Audit trail

Every lifecycle transition, credential rotation, and webhook change is recorded as an event. Query the audit trail for compliance and debugging:
curl -s https://api.zeam.money/gw/v1/application/$APP_ID/event \
  -H "Authorization: Bearer $TOKEN" | jq '.data'
Response:
[
  {
    "id": "event-uuid",
    "applicationId": "app-uuid",
    "eventType": "approved",
    "outcome": "success",
    "createdAt": "2026-05-10T14:30:00Z"
  },
  {
    "id": "event-uuid-2",
    "applicationId": "app-uuid",
    "eventType": "credential_rotated",
    "outcome": "success",
    "metadata": { "credentialId": "cred-uuid", "keyId": "ak_rotate_xyz" },
    "createdAt": "2026-05-10T15:00:00Z"
  }
]

5. Credential rotation

Rotate your API credential regularly as a security best practice. The new credential is returned once — store it immediately.
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/rotate-credential \
  -H "Authorization: Bearer $TOKEN" | jq '.data'
Response:
{
  "keyId": "ak_rotate_abc12345",
  "secret": "NEW_ONE_TIME_VISIBLE_SECRET",
  "last4": "cret"
}
The previous credential enters a rotating state and remains valid for a brief overlap period. Update your systems to use the new credential, then the old one expires automatically.

Token smoke test

After rotation, verify your credentials are working end-to-end:
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/token \
  -H "Authorization: Bearer $TOKEN" | jq
This drives the full Ed25519 auth flow server-side and confirms the integrator claim is valid.

6. Webhooks

Register webhook endpoints to receive real-time notifications for application and payment events. See the Webhooks guide for signature verification and best practices.

Add a webhook

curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/webhook \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://your-domain.com/webhooks/zeam",
    "webhookMethod": "POST",
    "authScheme": "hmac"
  }' | jq '.data'
The response includes a one-time-visible signing secret:
{
  "webhook": {
    "id": "webhook-uuid",
    "url": "https://your-domain.com/webhooks/zeam",
    "webhookMethod": "POST",
    "authScheme": "hmac",
    "status": "pending_verification"
  },
  "secret": {
    "webhookId": "webhook-uuid",
    "secret": "ONE_TIME_SIGNING_SECRET",
    "last4": "cret"
  }
}

List, update, and delete webhooks

# List
curl -s https://api.zeam.money/gw/v1/application/$APP_ID/webhook \
  -H "Authorization: Bearer $TOKEN" | jq '.data'

# Update (partial — include only fields to change)
curl -s -X PATCH https://api.zeam.money/gw/v1/application/$APP_ID/webhook/$WEBHOOK_ID \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://new-domain.com/webhooks/zeam"}' | jq '.data'

# Delete
curl -s -X DELETE https://api.zeam.money/gw/v1/application/$APP_ID/webhook/$WEBHOOK_ID \
  -H "Authorization: Bearer $TOKEN"

# Rotate signing secret
curl -s -X POST https://api.zeam.money/gw/v1/application/$APP_ID/webhook/$WEBHOOK_ID/rotate-secret \
  -H "Authorization: Bearer $TOKEN" | jq '.data'

Quick reference

ActionMethodPath
RegisterPOST/v1/application
ListGET/v1/applications/{association_id}
GetGET/v1/application/{id}
Lookup by keyGET/v1/application/lookup?publicKey=G...
EventsGET/v1/application/{id}/event
SubmitPOST/v1/application/{id}/submit
ApprovePOST/v1/application/{id}/approve
RejectPOST/v1/application/{id}/reject
SuspendPOST/v1/application/{id}/suspend
ResumePOST/v1/application/{id}/resume
RevokePOST/v1/application/{id}/revoke
Rotate credentialPOST/v1/application/{id}/rotate-credential
Token smoke testPOST/v1/application/{id}/token
List webhooksGET/v1/application/{id}/webhook
Add webhookPOST/v1/application/{id}/webhook
Update webhookPATCH/v1/application/{id}/webhook/{webhookId}
Delete webhookDELETE/v1/application/{id}/webhook/{webhookId}
Rotate webhook secretPOST/v1/application/{id}/webhook/{webhookId}/rotate-secret