Features
| Pricing | Documentation | Contact | Blog
Proxylity UDP Gateway's API Gateway destination enables "inside-out" integration, allowing UDP traffic to trigger external HTTP/HTTPS services beyond AWS. This capability bridges UDP protocols to REST APIs across cloud providers, automation platforms, custom webhooks, and enterprise systems—all while maintaining fine-grained IAM security controls.
The integration flow follows this pattern:
This architecture allows UDP-based devices and protocols to interact with modern HTTP APIs without protocol translation on the client side.
AWS API Gateway offers two API types with different transformation capabilities:
Use HTTP API when the external service can accept Proxylity's JSON packet format directly:
Use REST API when you need to adapt Proxylity's format to match external API schemas:
In practice, most external integrations require REST API because external services expect specific JSON structures that differ from Proxylity's packet format.
Here's a simple VTL template that transforms Proxylity's packet format to match a typical webhook API:
#set($packet = $input.path('$.Messages[0]'))
{
"event_type": "udp_packet_received",
"timestamp": "$packet.ReceivedAt",
"source_ip": "$packet.Remote.IpAddress",
"source_port": $packet.Remote.Port,
"payload": "$packet.Data",
"metadata": {
"listener": "$packet.Local.IpAddress:$packet.Local.Port",
"formatter": "$packet.Formatter"
}
}
This template extracts specific fields from the first packet in the batch and restructures them to match the external API's expected schema. REST API applies this transformation before sending the request to the backend.
For comprehensive VTL documentation, see AWS's mapping template reference.
Send UDP sensor data directly to cloud-based IoT platforms:
The same architectural pattern enables integration with serverless functions and managed services in other cloud providers:
Integration patterns that could work with no-code/low-code automation services:
Integrate with custom HTTP services and applications:
Reach on-premises and private network services securely:
For details on private API Gateway integrations, see AWS documentation on private integrations and private APIs.
Unlike public webhooks secured only by URL obscurity or shared API keys, API Gateway destinations leverage IAM for robust, auditable access control.
IAM policies can restrict Proxylity's access to specific API Gateway endpoints and stages:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAdafruitIO",
"Effect": "Allow",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:123456789012:abc123/prod/POST/adafruit/*"
},
{
"Sid": "AllowCustomDashboard",
"Effect": "Allow",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:123456789012:abc123/prod/POST/dashboard"
}
]
}
This policy explicitly authorizes Proxylity to invoke Adafruit IO feed endpoints and a custom dashboard. Any attempt to call other routes will be denied, even if someone discovers the API Gateway URL.
Following AWS best practices, create destination-specific IAM roles with minimal permissions:
Resources:
IoTPlatformRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !FindInMap [ProxylityConfig, !Ref "AWS::Region", ServiceRole]
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !FindInMap [ProxylityConfig, !Ref "AWS::Region", ExternalId]
Policies:
- PolicyName: InvokeIoTEndpoint
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: execute-api:Invoke
Resource: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ExternalApi}/prod/POST/iot/*"
This role can only invoke API Gateway endpoints under the /iot/ path, nothing else.
Debugging external service integrations requires visibility at multiple layers of the request flow.
Use composite destinations to log the original UDP packet data before any transformation:
Destinations:
- Name: external-api
DestinationArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGateway}/prod/POST/webhook"
Role:
RoleArn: !GetAtt ApiGatewayRole.Arn
- Name: udp-debug-logs
DestinationArn: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/proxylity/udp-packets"
Role:
RoleArn: !GetAtt UdpLoggingRole.Arn
This captures the raw UDP data Proxylity received, useful for verifying packet contents before transformation.
Enable CloudWatch logging in API Gateway to see:
Configure logging in your API Gateway stage settings:
ApiGatewayStage:
Type: AWS::ApiGateway::Stage
Properties:
StageName: prod
RestApiId: !Ref ApiGateway
DeploymentId: !Ref ApiGatewayDeployment
AccessLogSetting:
DestinationArn: !GetAtt ApiGatewayLogGroup.Arn
Format: '$context.requestId $context.error.message $context.error.messageString'
MethodSettings:
- ResourcePath: /*
HttpMethod: '*'
LoggingLevel: INFO
DataTraceEnabled: true
Set DataTraceEnabled: true to log full request/response bodies (be mindful of sensitive data).
Check the external service's own logging:
Symptom: External API returns 400 Bad Request or validation errors
Diagnosis: Compare API Gateway execution logs (transformed request) against external API's schema requirements
Solution: Adjust VTL mapping template to match expected schema
Symptom: External API returns 401 Unauthorized or 403 Forbidden
Diagnosis: Check if external service requires API keys, OAuth tokens, or specific headers
Solution: Add authentication headers in VTL template or API Gateway integration settings
Symptom: API Gateway returns 504 Gateway Timeout
Diagnosis: External service taking longer than API Gateway's 29-second timeout
Solution: Optimize external service or consider async pattern with callback webhook
Symptom: UDP client receives no reply packet
Diagnosis: Check if external API returned a response, and if API Gateway mapped it to Proxylity's response format
Solution: Ensure VTL response template transforms to {"Replies": [...]} format
Complete example showing API Gateway destination with external HTTP integration, IAM role, and composite logging:
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Proxylity UDP to External HTTP via API Gateway'
Resources:
# API Gateway REST API
ExternalIntegrationApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: udp-to-external-api
Description: Bridge UDP packets to external HTTP services
# Resource and Method
WebhookResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref ExternalIntegrationApi
ParentId: !GetAtt ExternalIntegrationApi.RootResourceId
PathPart: webhook
WebhookMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref ExternalIntegrationApi
ResourceId: !Ref WebhookResource
HttpMethod: POST
AuthorizationType: AWS_IAM
Integration:
Type: HTTP
IntegrationHttpMethod: POST
Uri: https://external-service.example.com/api/webhook
RequestTemplates:
application/json: |
#set($packet = $input.path('$.Messages[0]'))
{
"event": "udp_packet",
"data": "$packet.Data",
"source": "$packet.Remote.IpAddress",
"timestamp": "$packet.ReceivedAt"
}
IntegrationResponses:
- StatusCode: 200
ResponseTemplates:
application/json: |
{
"Replies": []
}
MethodResponses:
- StatusCode: 200
# Deployment
ApiDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: WebhookMethod
Properties:
RestApiId: !Ref ExternalIntegrationApi
StageName: prod
# Proxylity IAM Role
ProxylityApiGatewayRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !FindInMap [ProxylityConfig, !Ref "AWS::Region", ServiceRole]
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !FindInMap [ProxylityConfig, !Ref "AWS::Region", ExternalId]
Policies:
- PolicyName: InvokeWebhookEndpoint
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: execute-api:Invoke
Resource: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ExternalIntegrationApi}/prod/POST/webhook"
# CloudWatch Logs for UDP payload debugging
UdpPayloadLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /proxylity/udp-payloads
RetentionInDays: 7
UdpLoggingRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: !FindInMap [ProxylityConfig, !Ref "AWS::Region", ServiceRole]
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !FindInMap [ProxylityConfig, !Ref "AWS::Region", ExternalId]
Policies:
- PolicyName: WriteLogsPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !GetAtt UdpPayloadLogGroup.Arn
# Proxylity Listener with Composite Destinations
UdpListener:
Type: Custom::ProxylityUdpGatewayListener
Properties:
ServiceToken: !FindInMap [ProxylityConfig, !Ref "AWS::Region", ServiceToken]
ApiKey: !FindInMap [ProxylityConfig, !Ref "AWS::Region", ApiKey]
Protocols:
- udp
Destinations:
- Name: external-webhook
DestinationArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ExternalIntegrationApi}/prod/POST/webhook"
Role:
RoleArn: !GetAtt ProxylityApiGatewayRole.Arn
- Name: debug-logging
DestinationArn: !GetAtt UdpPayloadLogGroup.Arn
Role:
RoleArn: !GetAtt UdpLoggingRole.Arn
Outputs:
UdpEndpoint:
Description: UDP endpoint for sending packets
Value: !Sub "${UdpListener.Domain}.proxylity.com:${UdpListener.Port}"
ApiEndpoint:
Description: API Gateway endpoint
Value: !Sub "https://${ExternalIntegrationApi}.execute-api.${AWS::Region}.amazonaws.com/prod/webhook"
For complete working examples of UDP-to-HTTP integrations, see the udp-to-http folder in our examples repository, which includes:
Related documentation: