Trading Partners

Trading partners represent the organizations you exchange AS2 messages with. Each partner has specific configuration settings for AS2 communication including endpoint URLs, security preferences, and certificates.

Partner Management

List Partners

GET /v1/partners

Query Parameters:

  • search (string) - Search partner names or AS2 IDs
  • active (boolean) - Filter by active status
  • page (integer) - Page number for pagination
  • per_page (integer) - Items per page (max 100)

Response (200):

{
  "data": [
    {
      "id": "prt_000001",
      "name": "Acme Corporation",
      "as2_id": "ACME-CORP-AS2",
      "url": "https://acme.example.com/as2",
      "active": true,
      "sign": true,
      "encrypt": true,
      "compress": false,
      "mdn_mode": "async",
      "sign_algorithm": "SHA256withRSA",
      "encrypt_algorithm": "AES128_CBC",
      "created_at": "2024-01-01T10:00:00Z",
      "updated_at": "2024-01-15T14:30:00Z"
    }
  ],
  "pagination": {
    "current_page": 1,
    "last_page": 3,
    "per_page": 20,
    "total": 45
  }
}

Create Partner

POST /v1/partners

Request:

{
  "name": "New Partner Corp",
  "as2_id": "NEW-PARTNER-AS2",
  "url": "https://partner.example.com/as2",
  "sign": true,
  "encrypt": true,
  "compress": false,
  "mdn_mode": "async",
  "sign_algorithm": "SHA256withRSA",
  "encrypt_algorithm": "AES128_CBC"
}

Response (201):

{
  "message": "Partner created successfully",
  "data": {
    "id": "prt_000002",
    "name": "New Partner Corp",
    "as2_id": "NEW-PARTNER-AS2",
    "url": "https://partner.example.com/as2",
    "active": true,
    "sign": true,
    "encrypt": true,
    "compress": false,
    "mdn_mode": "async",
    "sign_algorithm": "SHA256withRSA",
    "encrypt_algorithm": "AES128_CBC",
    "created_at": "2024-01-15T10:30:00Z"
  }
}

Get Partner Details

GET /v1/partners/{partner_id}

Response (200):

{
  "data": {
    "id": "prt_000001",
    "name": "Acme Corporation",
    "as2_id": "ACME-CORP-AS2",
    "url": "https://acme.example.com/as2",
    "active": true,
    "sign": true,
    "encrypt": true,
    "compress": false,
    "mdn_mode": "async",
    "sign_algorithm": "SHA256withRSA",
    "encrypt_algorithm": "AES128_CBC",
    "certificates": [
      {
        "id": "cert_000001",
        "name": "Acme Corp Encryption Cert",
        "type": "partner",
        "subject": "CN=Acme Corp AS2, O=Acme Corporation",
        "active": true,
        "expires_at": "2025-01-01T00:00:00Z",
        "created_at": "2024-01-01T10:00:00Z"
      }
    ],
    "message_stats": {
      "total_sent": 1250,
      "total_received": 890,
      "last_message_at": "2024-01-15T10:00:00Z",
      "success_rate": 99.2
    },
    "created_at": "2024-01-01T10:00:00Z",
    "updated_at": "2024-01-15T14:30:00Z"
  }
}

Update Partner

PATCH /v1/partners/{partner_id}

Request:

{
  "name": "Updated Partner Name",
  "url": "https://new-endpoint.example.com/as2",
  "encrypt_algorithm": "AES256_CBC"
}

Delete Partner

DELETE /v1/partners/{partner_id}

Response (200):

{
  "message": "Partner deleted successfully"
}

Partner Configuration

Required Fields

FieldTypeDescription
namestringHuman-readable partner name
as2_idstringUnique AS2 identifier (no spaces)
urlstringPartner's AS2 receiving endpoint

Security Settings

FieldTypeDefaultDescription
signbooleanfalseEnable digital signatures
encryptbooleanfalseEnable message encryption
compressbooleanfalseEnable message compression
mdn_modeenumasyncMDN delivery mode: sync, async, none

Algorithm Options

Signing Algorithms:

  • SHA1withRSA - Legacy compatibility
  • SHA256withRSA - Recommended
  • SHA384withRSA - High security
  • SHA512withRSA - Maximum security

Encryption Algorithms:

  • 3DES - Legacy compatibility
  • AES128_CBC - Standard security
  • AES192_CBC - Enhanced security
  • AES256_CBC - Maximum security

Partner Certificates

List Partner Certificates

GET /v1/partners/{partner_id}/certificates

Response (200):

{
  "data": [
    {
      "id": "cert_000001",
      "name": "Acme Corp Public Key",
      "type": "partner",
      "usage": "encryption",
      "subject": "CN=Acme Corp AS2, O=Acme Corporation, C=US",
      "issuer": "CN=Acme CA, O=Acme Corporation",
      "serial_number": "123456789",
      "fingerprint": "SHA256:ab:cd:ef:12:34:56:78:90...",
      "active": true,
      "expires_at": "2025-01-01T00:00:00Z",
      "created_at": "2024-01-01T10:00:00Z"
    }
  ]
}

Upload Partner Certificate

POST /v1/partners/{partner_id}/certificates

Request (multipart/form-data):

curl -X POST https://api.as2aas.com/v1/partners/prt_000001/certificates \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "name=Partner Encryption Certificate" \
  -F "usage=encryption" \
  -F "[email protected]"

Response (201):

{
  "message": "Certificate uploaded successfully",
  "data": {
    "id": "cert_000002",
    "name": "Partner Encryption Certificate",
    "type": "partner",
    "usage": "encryption",
    "subject": "CN=Partner AS2",
    "active": true,
    "expires_at": "2025-06-01T00:00:00Z",
    "created_at": "2024-01-15T10:30:00Z"
  }
}

Partner Testing

Test Partner Connection

POST /v1/partners/{partner_id}/test

Request:

{
  "test_type": "ping"
}

Response (200):

{
  "success": true,
  "message": "Partner connection test successful",
  "data": {
    "test_type": "ping",
    "partner": {
      "id": "prt_000001",
      "name": "Acme Corp",
      "as2_id": "ACME-CORP-AS2",
      "url": "https://acme.example.com/as2"
    },
    "results": {
      "connectivity": "success",
      "response_time_ms": 245,
      "ssl_valid": true,
      "certificate_valid": true,
      "as2_headers_supported": true
    },
    "timeline": [
      {
        "step": "DNS resolution",
        "status": "success",
        "duration_ms": 12,
        "details": "Resolved to 203.0.113.10"
      },
      {
        "step": "TCP connection",
        "status": "success", 
        "duration_ms": 89,
        "details": "Connected to port 443"
      },
      {
        "step": "SSL handshake",
        "status": "success",
        "duration_ms": 144,
        "details": "TLS 1.3 connection established"
      }
    ]
  }
}

Test Types

Test TypeDescription
pingBasic connectivity test
mdnMDN response test
fullComplete AS2 handshake test

Partner Status Management

Activate Partner

POST /v1/partners/{partner_id}/activate

Deactivate Partner

POST /v1/partners/{partner_id}/deactivate

Response:

{
  "message": "Partner deactivated successfully",
  "data": {
    "id": "prt_000001",
    "active": false,
    "deactivated_at": "2024-01-15T10:30:00Z"
  }
}

Partner Analytics

Message Statistics

GET /v1/partners/{partner_id}/stats

Response (200):

{
  "data": {
    "partner_id": "prt_000001",
    "partner_name": "Acme Corp",
    "period": "last_30_days",
    "messages": {
      "sent": 450,
      "received": 320,
      "total": 770
    },
    "success_rates": {
      "outbound": 99.3,
      "inbound": 100.0,
      "overall": 99.6
    },
    "avg_processing_times": {
      "outbound_seconds": 8.2,
      "inbound_seconds": 3.1
    },
    "recent_activity": [
      {
        "date": "2024-01-15",
        "sent": 25,
        "received": 18,
        "failures": 0
      }
    ]
  }
}

Integration Patterns

Automatic Partner Discovery

// Automatically create partners when they send messages
app.post('/webhooks/as2', async (req, res) => {
  const { event, data } = req.body;
  
  if (event === 'partner.unknown') {
    // Create partner automatically from first message
    const partner = await as2.partners.create({
      name: `Auto: ${data.from_as2_id}`,
      as2_id: data.from_as2_id,
      url: data.sender_url || 'https://unknown-partner.com/as2',
      active: false // Require manual activation
    });
    
    console.log('Auto-created partner:', partner.id);
    
    // Notify admin for review
    await notifyAdmin(`New partner auto-created: ${partner.name}`);
  }
  
  res.status(200).send('OK');
});

Partner Health Monitoring

// Monitor all partner connectivity
async function checkPartnerHealth() {
  const partners = await as2.partners.list({ active: true });
  
  for (const partner of partners.data) {
    try {
      const test = await as2.partners.test(partner.id, { test_type: 'ping' });
      
      if (!test.success) {
        await alertPartnerDown(partner);
      }
    } catch (error) {
      await logPartnerError(partner, error);
    }
  }
}

// Run health checks every hour
setInterval(checkPartnerHealth, 60 * 60 * 1000);

Dynamic Configuration

// Update partner settings based on message patterns
async function optimizePartnerConfig(partnerId) {
  const stats = await as2.partners.getStats(partnerId);
  
  // Enable compression if average message size > 50KB
  if (stats.avg_message_size > 50 * 1024) {
    await as2.partners.update(partnerId, { compress: true });
  }
  
  // Adjust retry settings based on success rate
  if (stats.success_rate < 95) {
    await as2.partners.update(partnerId, {
      retry_attempts: 5,
      retry_interval: 600 // 10 minutes
    });
  }
}

Partner Onboarding

Onboarding Workflow

  1. Create Partner Record
  2. Exchange Certificates
  3. Test Connectivity
  4. Send Test Message
  5. Activate Partner

Automated Onboarding

async function onboardNewPartner(partnerInfo) {
  // Step 1: Create partner
  const partner = await as2.partners.create({
    name: partnerInfo.name,
    as2_id: partnerInfo.as2_id,
    url: partnerInfo.endpoint,
    active: false
  });
  
  // Step 2: Upload their certificate
  if (partnerInfo.certificate) {
    await as2.certificates.upload({
      partner_id: partner.id,
      name: `${partner.name} Public Key`,
      certificate: partnerInfo.certificate,
      usage: 'encryption'
    });
  }
  
  // Step 3: Test connectivity
  const connectionTest = await as2.partners.test(partner.id, {
    test_type: 'ping'
  });
  
  if (!connectionTest.success) {
    throw new Error(`Partner connectivity test failed: ${connectionTest.message}`);
  }
  
  // Step 4: Send test message
  const testMessage = await as2.messages.test({
    partner_id: partner.id,
    message_type: 'test'
  });
  
  // Step 5: Activate if all tests pass
  if (testMessage.success) {
    await as2.partners.update(partner.id, { active: true });
    return partner;
  } else {
    throw new Error('Test message failed');
  }
}

Security Configuration

Certificate Requirements

For Encryption (Outbound):

  • Upload partner's public certificate
  • Used to encrypt messages you send to them

For Signature Verification (Inbound):

  • Upload partner's public certificate
  • Used to verify signatures on messages they send to you

For Your Identity:

  • Upload your private certificate (identity certificate)
  • Used for signing outbound messages and decrypting inbound messages

Certificate Management

# Upload partner's public certificate for encryption
curl -X POST https://api.as2aas.com/v1/partners/prt_000001/certificates \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "name=Partner Encryption Cert" \
  -F "usage=encryption" \
  -F "[email protected]"

# Upload partner's public certificate for signature verification
curl -X POST https://api.as2aas.com/v1/partners/prt_000001/certificates \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "name=Partner Signing Cert" \
  -F "usage=signing" \
  -F "[email protected]"

Algorithm Selection

Choose algorithms based on partner capabilities and security requirements:

Recommended Combinations:

{
  "sign_algorithm": "SHA256withRSA",
  "encrypt_algorithm": "AES256_CBC"
}

Legacy Compatibility:

{
  "sign_algorithm": "SHA1withRSA", 
  "encrypt_algorithm": "3DES"
}

Maximum Security:

{
  "sign_algorithm": "SHA512withRSA",
  "encrypt_algorithm": "AES256_CBC"
}

Partner Validation

Configuration Validation

POST /v1/partners/{partner_id}/validate

Response (200):

{
  "valid": true,
  "checks": [
    {
      "name": "AS2 ID Format",
      "status": "pass",
      "message": "AS2 ID follows standard format"
    },
    {
      "name": "Endpoint Accessibility",
      "status": "pass", 
      "message": "Partner endpoint is reachable"
    },
    {
      "name": "Certificate Validity",
      "status": "pass",
      "message": "All certificates are valid and not expired"
    },
    {
      "name": "Algorithm Compatibility",
      "status": "pass",
      "message": "Selected algorithms are supported"
    }
  ]
}

Common Validation Issues

IssueCauseSolution
INVALID_AS2_IDAS2 ID contains spaces/special charsUse alphanumeric and hyphens only
UNREACHABLE_ENDPOINTCannot connect to partner URLVerify URL and network access
EXPIRED_CERTIFICATEPartner certificate has expiredUpload new certificate
UNSUPPORTED_ALGORITHMAlgorithm not supported by partnerChoose compatible algorithm

Error Handling

Partner-Specific Errors

{
  "error": {
    "type": "partner_error",
    "code": "PARTNER_CERTIFICATE_EXPIRED",
    "message": "Partner's encryption certificate expired on 2024-01-10",
    "details": {
      "partner_id": "prt_000001",
      "certificate_id": "cert_000001",
      "expired_at": "2024-01-10T00:00:00Z"
    }
  }
}

Handling Partner Errors

try {
  await as2.messages.create({
    partner: 'problematic-partner',
    payload: { content: ediContent }
  });
} catch (error) {
  switch (error.code) {
    case 'PARTNER_NOT_FOUND':
      // Partner doesn't exist - create it
      await createPartner(error.details.as2_id);
      break;
      
    case 'PARTNER_INACTIVE':
      // Partner is deactivated - check why
      await checkPartnerStatus(error.details.partner_id);
      break;
      
    case 'CERTIFICATE_EXPIRED':
      // Certificate needs renewal
      await requestCertificateUpdate(error.details.partner_id);
      break;
  }
}

Advanced Partner Features

Partner Groups

Organize partners into logical groups:

{
  "name": "Acme Corp",
  "as2_id": "ACME-CORP-AS2",
  "group": "tier-1-suppliers",
  "priority": "high"
}

Custom Partner Settings

{
  "name": "Special Partner",
  "as2_id": "SPECIAL-PARTNER",
  "custom_settings": {
    "retry_attempts": 10,
    "retry_interval": 300,
    "timeout_seconds": 120,
    "max_message_size": "200MB"
  }
}

Partner Webhooks

Configure partner-specific webhook events:

{
  "webhook_settings": {
    "message_events": true,
    "error_events": true,
    "certificate_events": true,
    "custom_endpoint": "https://your-app.com/webhooks/partner-001"
  }
}

Troubleshooting Partners

Connection Issues

Test Partner Connectivity:

POST /v1/partners/{partner_id}/test

Common Connection Problems:

  • Firewall blocking outbound connections
  • Invalid SSL certificates on partner endpoint
  • AS2 ID mismatch in configuration
  • Partner endpoint downtime

Certificate Issues

Check Certificate Status:

GET /v1/certificates?partner_id={partner_id}

Common Certificate Problems:

  • Expired certificates
  • Wrong certificate type (public vs private)
  • Certificate format issues (PEM vs DER)
  • Missing certificate chain

Message Delivery Issues

Review Failed Messages:

GET /v1/messages?partner_id={partner_id}&status=failed

Common Delivery Problems:

  • Partner endpoint rejecting messages
  • Size limits exceeded
  • Unsupported content types
  • MDN configuration mismatches

Best Practices

Partner Naming

  • Use descriptive names: "Acme Corp - Production"
  • Include environment: "Partner Name - Test"
  • Avoid special characters in AS2 IDs

Security Configuration

  • Always enable encryption for sensitive data
  • Use SHA256 or higher for signing algorithms
  • Regularly rotate certificates
  • Test configuration changes thoroughly

Monitoring

  • Set up webhook notifications for partner events
  • Monitor partner connection health
  • Track message success rates by partner
  • Alert on certificate expiry

Performance

  • Enable compression for large messages
  • Use appropriate timeout values
  • Consider partner processing capabilities
  • Monitor and optimize retry settings

Getting Help

For partner configuration issues:

  1. Use testing tools in your dashboard
  2. Review connection test results for specific errors
  3. Check certificate validity and expiration dates
  4. Contact support with partner ID for assistance