Skip to main content

Project Management

Learn how to manage projects, retrieve project information, and understand project-wallet relationships.

What is a Project?​

A project represents a business entity or service in the Paysera system. Each project:

  • Has an owner (user or company)
  • Has a default wallet for receiving payments
  • Can be accessed by multiple clients
  • Organizes related resources and permissions

Get Project by ID​

Retrieve detailed information about a specific project.

Request

GET /rest/v1/project/{projectId}

Parameters

ParameterTypeRequiredDescription
projectIdinteger✅ YesID of the project

Response

{
"id": 1221,
"title": "My E-Commerce Store",
"description": "Online payment processing for my store",
"wallet_id": 2112,
"owner_display_name": "John's Company Ltd"
}
View Response Fields
FieldTypeAlways PresentDescription
idinteger✅ YesProject ID
titlestring✅ YesProject title
descriptionstring⬜ OptionalProject description
wallet_idinteger⬜ OptionalAssociated wallet ID
owner_display_namestring⬜ OptionalOwner's display name

Example

async function getProjectInfo(projectId) {
const project = await api.getProject(projectId);

console.log(`Project: ${project.title}`);
console.log(`Owner: ${project.owner_display_name}`);
console.log(`Wallet ID: ${project.wallet_id}`);

return project;
}

// Usage
const project = await getProjectInfo(1221);

Get User's Administered Projects​

Retrieve all projects that a user can administer.

Request

GET /rest/v1/user/{userId}/projects

Parameters

ParameterTypeRequiredDescription
userIdinteger or me✅ YesUser ID or me for current user
Using 'me'

When using access tokens, you can use me instead of the user ID to get projects for the authenticated user.

Required Scope: projects - This endpoint requires the projects OAuth scope.

Response: Array of project objects

[
{
"id": 1221,
"title": "My E-Commerce Store",
"description": "Online payment processing",
"wallet_id": 2112,
"owner_display_name": "John's Company Ltd"
},
{
"id": 1222,
"title": "My Second Project",
"wallet_id": 2113,
"owner_display_name": "John's Company Ltd"
}
]
View Example
async function getUserProjects(userId = 'me') {
const projects = await api.getUserProjects(userId);

console.log(`Found ${projects.length} projects:`);
projects.forEach(p => {
console.log(`- ${p.title} (ID: ${p.id})`);
});

return projects;
}

// Usage with access token
const myProjects = await getUserProjects('me');

// Usage with specific user ID
const userProjects = await getUserProjects(1234);

Project-Wallet Relationship​

Understanding how projects and wallets work together.

Key Points

  1. Each project has a default wallet for receiving payments
  2. Wallet belongs to the project owner (user or company)
  3. Multiple projects can share the same wallet (if they have the same owner)
  4. Clients can specify project using project_id parameter

Diagram

Example Scenario:

  • Company owns Wallet 1 and Wallet 2
  • Project A and Project B use Wallet 1
  • Project C uses Wallet 2
  • Each project can have multiple clients

Using project_id Parameter​

When a client can access multiple projects, specify which project using the project_id parameter.

When to Use

  • ✅ Client manages multiple projects
  • ✅ Access token has projects scope
  • ✅ Need to specify target project for operation
How to Pass project_id

With MAC Authentication

Include in ext field:

GET /rest/v1/wallet/14471/balance HTTP/1.1
Host: wallet.paysera.com
Authorization: MAC id="wkVd93h2uS",
ts="1343811600",
nonce="nQnNaSNyubfPErjRO55yaaEYo9YZfKHN",
mac="EOhN6gBf49tR2KxMflaaiN7bBVGDhfG6co8gcSBLyiQ=",
ext="project_id=1221"

With SSL Certificate

Use custom header:

GET /rest/v1/wallet/14471/balance HTTP/1.1
Host: wallet.paysera.com
Wallet-Api-Project-Id: 1221
Implementation Example
class MultiProjectClient {
constructor(credentials) {
this.client = new PayseraClient(credentials);
this.projects = [];
}

async initialize() {
// Load all available projects
this.projects = await this.client.getUserProjects('me');
console.log(`Loaded ${this.projects.length} projects`);
}

async getWalletBalance(walletId, projectId) {
// Make request with project_id
return await this.client.request('/wallet/' + walletId + '/balance', {
headers: {
'Wallet-Api-Project-Id': projectId
}
});
}

async getAllProjectBalances() {
const balances = [];

for (const project of this.projects) {
try {
const balance = await this.getWalletBalance(
project.wallet_id,
project.id
);

balances.push({
project: project.title,
wallet_id: project.wallet_id,
balance: balance
});
} catch (error) {
console.error(`Error for project ${project.id}:`, error);
}
}

return balances;
}
}

// Usage
const client = new MultiProjectClient(credentials);
await client.initialize();

const balances = await client.getAllProjectBalances();
balances.forEach(b => {
console.log(`${b.project}: ${b.balance.amount} ${b.balance.currency}`);
});

Advanced Topics​

Project Setup Workflow

For New Integration

  1. Contact Paysera Support

    • Describe your use case
    • Provide business details
    • Request project creation
  2. Receive Project Credentials

    • Project ID
    • Client credentials
    • Wallet information
  3. Configure Your Application

    const config = {
    projectId: 1221,
    clientId: 'your_client_id',
    macKey: 'your_mac_key',
    walletId: 2112
    };
  4. Test Thoroughly

    • Test with small amounts
    • Test all operations
    • Verify payment flows
  5. Monitor & Scale

    • Monitor operations
    • Gradually increase volumes
    • Track performance
Best Practice 1: Cache Project Information
class ProjectCache {
constructor(api, ttl = 3600000) { // 1 hour default
this.api = api;
this.ttl = ttl;
this.cache = new Map();
}

async getProject(projectId) {
const cached = this.cache.get(projectId);

if (cached && Date.now() - cached.timestamp < this.ttl) {
return cached.data;
}

const project = await this.api.getProject(projectId);

this.cache.set(projectId, {
data: project,
timestamp: Date.now()
});

return project;
}

clearCache() {
this.cache.clear();
}
}

// Usage
const cache = new ProjectCache(api);
const project = await cache.getProject(1221); // Fetches from API
const sameProject = await cache.getProject(1221); // Returns from cache
Best Practice 2: Handle Multiple Projects
async function selectProject(projects, preferredId = null) {
if (projects.length === 0) {
throw new Error('No projects available');
}

if (projects.length === 1) {
return projects[0];
}

// Try to use preferred project
if (preferredId) {
const preferred = projects.find(p => p.id === preferredId);
if (preferred) return preferred;
}

// Or show selection UI
return await showProjectSelector(projects);
}
Best Practice 3: Validate Project Access
async function ensureProjectAccess(projectId) {
const projects = await api.getUserProjects('me');
const hasAccess = projects.some(p => p.id === projectId);

if (!hasAccess) {
throw new Error(
`No access to project ${projectId}. ` +
`Available projects: ${projects.map(p => p.id).join(', ')}`
);
}
}

// Before using project
await ensureProjectAccess(1221);
await api.createPayment({ project_id: 1221, ... });
Best Practice 4: Store Configuration
// config.json
{
"production": {
"project_id": 1221,
"wallet_id": 2112,
"client_id": "your_client_id"
}
}

// Load configuration
const config = require('./config.json').production;

const client = new PayseraClient({
clientId: config.client_id,
projectId: config.project_id
});
Production Only

Wallet API operates in production environment only. Store your production credentials securely.

Common Scenarios

Scenario 1: Single Project Integration

Use Case: E-commerce store with one payment project

// Simple setup - hardcode project ID
const PROJECT_ID = 1221;

async function createPayment(orderData) {
return await api.createTransaction({
project_id: PROJECT_ID,
payments: [/* ... */]
});
}

Scenario 2: Multi-Project Dashboard

Use Case: Admin dashboard managing multiple projects

class ProjectDashboard {
async loadProjects() {
this.projects = await api.getUserProjects('me');
}

async getProjectStats(projectId) {
const stats = await api.request('/stats', {
headers: { 'Wallet-Api-Project-Id': projectId }
});

return {
project: this.projects.find(p => p.id === projectId),
stats: stats
};
}

async getAllStats() {
return await Promise.all(
this.projects.map(p => this.getProjectStats(p.id))
);
}
}

Scenario 3: Project Switching

Use Case: App that lets users switch between projects

class ProjectSwitcher {
constructor() {
this.currentProject = null;
}

async switchProject(projectId) {
const projects = await api.getUserProjects('me');
const project = projects.find(p => p.id === projectId);

if (!project) {
throw new Error(`Project ${projectId} not found`);
}

this.currentProject = project;
this.updateUI(project);
await storage.set('selectedProject', projectId);
}

getCurrentProjectId() {
return this.currentProject?.id;
}
}
Troubleshooting

Issue: "Project not found"

Cause: Invalid project ID or no access

Solution:

try {
const project = await api.getProject(projectId);
} catch (error) {
if (error.code === 'not_found') {
console.error('Project not found. Check project ID.');
const available = await api.getUserProjects('me');
console.log('Available projects:', available.map(p => p.id));
}
}

Issue: "Forbidden" when accessing project

Cause: Client doesn't have permission for this project

Solution:

// Check if project_id matches client's project
const clientInfo = await api.getClient();
const projects = await api.getUserProjects('me');

console.log('Client projects:', projects.map(p => p.id));

Issue: Multiple projects, unclear which to use

Cause: No project_id specified

Solution:

// Always specify project_id when managing multiple projects
await api.createPayment({
project_id: selectedProjectId, // Always include!
payments: [/* ... */]
});

Next Steps​