setup-payram
π―Skillfrom payram/payram-helper-mcp-server
Configures and validates connectivity to a self-hosted Payram server by setting up environment variables and testing API authentication.
Part of
payram/payram-helper-mcp-server(14 items)
Installation
pip install requests python-dotenvSkill Details
Configure and validate connectivity to a self-hosted Payram server
Overview
# Setup Payram
Configure your backend to connect to a self-hosted Payram server and validate the connection.
Overview
This skill guides you through:
- Creating the required
.envconfiguration - Understanding Payram's authentication model
- Testing connectivity to your Payram instance
- Troubleshooting common connection issues
When to Use
- Starting a new Payram integration
- Validating existing Payram configuration
- Troubleshooting connection errors
- Setting up a new environment (staging, production)
Prerequisites
You must have:
- A self-hosted Payram server deployed and accessible
- Admin access to the Payram dashboard
- An API key generated from the dashboard (Settings β Accounts β API Keys)
Instructions
Step 1: Create Environment Configuration
Create a .env file in your project root with the following variables:
```bash
# Payram REST base URL (include protocol, no trailing slash)
PAYRAM_BASE_URL=https://your-payram-server.example
# Payram API key (from dashboard Settings β Accounts β API Keys)
PAYRAM_API_KEY=pk_live_your_actual_key_here
```
Required Variables:
PAYRAM_BASE_URL: Full URL to your self-hosted Payram instancePAYRAM_API_KEY: Project-scoped API key from the Payram dashboard
Important: Never commit .env files to version control. Add .env to your .gitignore.
Step 2: Understand Authentication
Payram uses header-based authentication:
```
API-Key: your_api_key_here
```
NOT Authorization: Bearer ... - this will fail with 401.
The API key must be:
- Sent in the
API-Keyheader (case-sensitive) - Generated for the specific project/workspace you're integrating
- Kept secret and never exposed in client-side code
Step 3: Test Connectivity
Create a test script to validate your connection. The connection test creates a minimal payment request to verify:
- Network reachability
- API key validity
- Correct authentication setup
#### Node.js/TypeScript (Using Payram SDK)
Install SDK:
```bash
npm install payram dotenv
```
Test Script:
```typescript
import { Payram, isPayramSDKError } from 'payram';
import dotenv from 'dotenv';
dotenv.config();
const baseUrl = process.env.PAYRAM_BASE_URL;
const apiKey = process.env.PAYRAM_API_KEY;
if (!baseUrl || !apiKey) {
console.error('β Missing PAYRAM_BASE_URL or PAYRAM_API_KEY in .env');
process.exit(1);
}
async function testConnection() {
try {
// Initialize Payram SDK
const payram = new Payram({
apiKey,
baseUrl,
config: {
timeoutMs: 10_000,
maxRetries: 2,
},
});
console.log('π Testing connection to Payram...');
console.log( Base URL: ${baseUrl});
// Create a minimal test payment
const checkout = await payram.payments.initiatePayment({
customerEmail: 'test@example.com',
customerId: 'connectivity-test',
amountInUSD: 1,
});
console.log('β Connection successful!');
console.log( Reference ID: ${checkout.reference_id});
console.log( Checkout URL: ${checkout.url});
return true;
} catch (error) {
console.error('β Connection failed');
if (isPayramSDKError(error)) {
console.error( Status: ${error.status});
console.error( Error: ${error.error});
console.error( Request ID: ${error.requestId});
console.error( Retryable: ${error.isRetryable});
} else {
console.error( Error: ${error instanceof Error ? error.message : String(error)});
}
return false;
}
}
testConnection();
```
#### Python (Using requests)
Install dependencies:
```bash
pip install requests python-dotenv
```
Test Script:
```python
import os
import requests
from dotenv import load_dotenv
load_dotenv()
base_url = os.getenv('PAYRAM_BASE_URL')
api_key = os.getenv('PAYRAM_API_KEY')
if not base_url or not api_key:
print('β Missing PAYRAM_BASE_URL or PAYRAM_API_KEY in .env')
exit(1)
def test_connection():
try:
print('π Testing connection to Payram...')
print(f' Base URL: {base_url}')
endpoint = f"{base_url}/api/v1/payment"
headers = {
'API-Key': api_key,
'Content-Type': 'application/json',
'Accept': 'application/json',
}
payload = {
'customerEmail': 'test@example.com',
'customerId': 'connectivity-test',
'amountInUSD': 1,
}
response = requests.post(endpoint, json=payload, headers=headers, timeout=10)
if response.status_code in [200, 201]:
data = response.json()
print('β Connection successful!')
print(f" Reference ID: {data.get('reference_id', 'N/A')}")
print(f" Checkout URL: {data.get('url', 'N/A')}")
return True
else:
print('β Connection failed')
print(f" Status: {response.status_code}")
print(f" Response: {response.text}")
return False
except requests.exceptions.RequestException as e:
print('β Connection failed')
print(f" Error: {str(e)}")
return False
if __name__ == '__main__':
test_connection()
```
#### Go (Using net/http)
Test Script:
```go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"time"
"github.com/joho/godotenv"
)
type PaymentRequest struct {
CustomerEmail string json:"customerEmail"
CustomerID string json:"customerId"
AmountInUSD float64 json:"amountInUSD"
}
type PaymentResponse struct {
ReferenceID string json:"reference_id"
URL string json:"url"
}
func testConnection() bool {
godotenv.Load()
baseURL := os.Getenv("PAYRAM_BASE_URL")
apiKey := os.Getenv("PAYRAM_API_KEY")
if baseURL == "" || apiKey == "" {
fmt.Println("β Missing PAYRAM_BASE_URL or PAYRAM_API_KEY in .env")
return false
}
fmt.Println("π Testing connection to Payram...")
fmt.Printf(" Base URL: %s\n", baseURL)
payload := PaymentRequest{
CustomerEmail: "test@example.com",
CustomerID: "connectivity-test",
AmountInUSD: 1.0,
}
body, _ := json.Marshal(payload)
client := &http.Client{Timeout: 10 * time.Second}
req, err := http.NewRequest("POST", baseURL+"/api/v1/payment", bytes.NewBuffer(body))
if err != nil {
fmt.Printf("β Failed to create request: %v\n", err)
return false
}
req.Header.Set("API-Key", apiKey)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
resp, err := client.Do(req)
if err != nil {
fmt.Printf("β Connection failed: %v\n", err)
return false
}
defer resp.Body.Close()
if resp.StatusCode == 200 || resp.StatusCode == 201 {
var result PaymentResponse
bodyBytes, _ := io.ReadAll(resp.Body)
json.Unmarshal(bodyBytes, &result)
fmt.Println("β Connection successful!")
fmt.Printf(" Reference ID: %s\n", result.ReferenceID)
fmt.Printf(" Checkout URL: %s\n", result.URL)
return true
} else {
fmt.Printf("β Connection failed: Status %d\n", resp.StatusCode)
bodyBytes, _ := io.ReadAll(resp.Body)
fmt.Printf(" Response: %s\n", string(bodyBytes))
return false
}
}
func main() {
testConnection()
}
```
#### PHP (Using cURL)
Test Script:
```php
require __DIR__ . '/vendor/autoload.php';
use Dotenv\Dotenv;
$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();
$baseUrl = $_ENV['PAYRAM_BASE_URL'] ?? null;
$apiKey = $_ENV['PAYRAM_API_KEY'] ?? null;
if (!$baseUrl || !$apiKey) {
echo "β Missing PAYRAM_BASE_URL or PAYRAM_API_KEY in .env\n";
exit(1);
}
function testConnection($baseUrl, $apiKey) {
echo "π Testing connection to Payram...\n";
echo " Base URL: $baseUrl\n";
$payload = [
'customerEmail' => 'test@example.com',
'customerId' => 'connectivity-test',
'amountInUSD' => 1,
];
$ch = curl_init($baseUrl . '/api/v1/payment');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'API-Key: ' . $apiKey,
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
echo "β Connection failed: $error\n";
return false;
}
if ($statusCode === 200 || $statusCode === 201) {
$data = json_decode($response, true);
echo "β Connection successful!\n";
echo " Reference ID: " . ($data['reference_id'] ?? 'N/A') . "\n";
echo " Checkout URL: " . ($data['url'] ?? 'N/A') . "\n";
return true;
} else {
echo "β Connection failed: Status $statusCode\n";
echo " Response: $response\n";
return false;
}
}
testConnection($baseUrl, $apiKey);
```
#### Java (Using HttpClient)
Test Script:
```java
package com.example.payram;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import io.github.cdimascio.dotenv.Dotenv;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class ConnectionTest {
public static void main(String[] args) {
Dotenv dotenv = Dotenv.load();
String baseUrl = dotenv.get("PAYRAM_BASE_URL");
String apiKey = dotenv.get("PAYRAM_API_KEY");
if (baseUrl == null || apiKey == null) {
System.out.println("β Missing PAYRAM_BASE_URL or PAYRAM_API_KEY in .env");
System.exit(1);
}
testConnection(baseUrl, apiKey);
}
public static boolean testConnection(String baseUrl, String apiKey) {
try {
System.out.println("π Testing connection to Payram...");
System.out.println(" Base URL: " + baseUrl);
// Create JSON payload
ObjectMapper mapper = new ObjectMapper();
ObjectNode payload = mapper.createObjectNode();
payload.put("customerEmail", "test@example.com");
payload.put("customerId", "connectivity-test");
payload.put("amountInUSD", 1);
// Build HTTP request
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/api/v1/payment"))
.header("API-Key", apiKey)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(mapper.writeValueAsString(payload)))
.timeout(Duration.ofSeconds(10))
.build();
// Send request
HttpResponse
if (response.statusCode() == 200 || response.statusCode() == 201) {
ObjectNode result = (ObjectNode) mapper.readTree(response.body());
System.out.println("β Connection successful!");
System.out.println(" Reference ID: " + result.get("reference_id").asText());
System.out.println(" Checkout URL: " + result.get("url").asText());
return true;
} else {
System.out.println("β Connection failed: Status " + response.statusCode());
System.out.println(" Response: " + response.body());
return false;
}
} catch (Exception e) {
System.out.println("β Connection failed: " + e.getMessage());
return false;
}
}
}
```
Step 4: Interpret Results
Success (200/201):
```json
{
"checkout": {
"id": "...",
"url": "https://...",
...
}
}
```
Your configuration is correct and Payram is reachable.
401 Unauthorized:
- Check that
API-Keyheader is used (notAuthorization) - Verify the API key is correct and hasn't been revoked
- Ensure the key is for the correct project/workspace
404 Not Found:
- Verify
PAYRAM_BASE_URLis correct - Check for typos in the endpoint path
- Confirm Payram is deployed and running
Network Errors:
- Verify firewall rules allow outbound HTTPS
- Check DNS resolution of your Payram domain
- Confirm SSL certificates are valid
Best Practices
- Environment Separation
- Use different API keys for staging vs production
- Never share API keys between environments
- Rotate keys regularly
- Security
- Store API keys in secure secret management systems (AWS Secrets Manager, Vault, etc.)
- Never log full API keys
- Use environment-specific .env files (.env.staging, .env.production)
- Error Handling
- Always check response status codes
- Log failures with context but without sensitive data
- Implement retry logic with exponential backoff for network errors
- Validation
- Test connectivity before deploying to production
- Run connectivity tests as part of CI/CD health checks
- Monitor connection health in production with periodic pings
Troubleshooting
"Missing PAYRAM_BASE_URL or PAYRAM_API_KEY"
Cause: Environment variables not loaded.
Solution:
- Ensure
.envfile exists in project root - Verify
.envcontains both variables - Check that your code loads
.env(e.g.,dotenv.config()in Node,load_dotenv()in Python)
"401 Unauthorized" or "Authentication Failed"
Cause: Invalid or missing API key.
Solution:
- Confirm you're using
API-Keyheader, notAuthorization - Regenerate API key in Payram dashboard if needed
- Check for extra whitespace in
.envvalues
"Network error" or "Connection refused"
Cause: Payram server unreachable.
Solution:
- Verify
PAYRAM_BASE_URLincludes protocol (https://) - Check firewall rules and network connectivity
- Confirm Payram service is running (
systemctl status payram)
"404 Not Found"
Cause: Wrong endpoint or base URL.
Solution:
- Remove trailing slashes from
PAYRAM_BASE_URL - Verify endpoint path is
/api/v1/payment - Check Payram version compatibility
Related Skills
integrate-payments- After setup, implement payment flowsintegrate-payouts- Configure outbound payment capabilitieshandle-webhooks- Receive Payram event notifications
More from this repository10
Skill
Skill
Skill
Enables real-time payment status updates by securely implementing webhook handlers across multiple frameworks for Payram integrations.
Skill
Skill
Skill
Skill
Skill
Enables seamless cryptocurrency payment integration by creating checkouts, redirecting customers, and tracking payment statuses across multiple languages and frameworks.