# pai-event

Part of **PAI**

# Platform for AI (PAI) Event Integration

## Capabilities Overview

| Sub-capability | Calling Mode | Description |
|----------------|--------------|-------------|
| Accept DataWorks Event | Synchronous | Process incoming events from Alibaba Cloud DataWorks. |

## API Calling Patterns

### Authentication
This API is intended for **internal system integration** between PAI and DataWorks and **does not require explicit authentication** in typical usage scenarios. However, if called externally (e.g., during testing or custom integration), ensure the request originates from an authorized Alibaba Cloud service context.

- No `Authorization` header is required in standard operation.
- If access control is enforced by network policy, calls must originate from within Alibaba Cloud's trusted network or via VPC peering.
- Environment variables for credentials are **not applicable** for this endpoint under normal conditions.

> **Note**: This endpoint is not publicly exposed and is primarily invoked by DataWorks as part of its extension point mechanism.

### Service Endpoint
The API uses region-agnostic global endpoints based on deployment scope:

- **China Region**: `https://api.aliyun.com/api/AIWorkSpace/2021-02-04/AcceptDataworksEvent`
- **International Region**: `https://api.alibabacloud.com/api/AIWorkSpace/2021-02-04/AcceptDataworksEvent`

Both endpoints accept `POST` requests with JSON payloads.

### Synchronous Request Pattern
This API follows a standard synchronous request-response flow:

1. DataWorks triggers an extension point event and sends an HTTP POST request to the PAI endpoint.
2. The request includes a JSON body containing `MessageId` and `Data`.
3. PAI processes the event immediately and returns a JSON response with a `requestId`.
4. The caller (DataWorks) receives the response synchronously; no polling or async handling is needed.

Key characteristics:
- Single round-trip interaction
- Immediate processing and response
- No streaming or long-running operations

## Parameter Reference

### Accept DataWorks Event

| Parameter | Type | Required | Default | Constraints | Description |
|----------|------|----------|---------|-------------|-------------|
| MessageId | string | false | — | — | The ID of the DataWorks open message. After an extension point event is triggered, the message ID is available in the received event message. For more information about the message format, see Message format. |
| Data | object | false | — | — | The event content of the message. Contains structured event details such as `eventCode`, `projectId`, `tenantId`, and `operator`. |

> **Note**: While marked as optional in schema definitions, both `MessageId` and `Data` are **effectively required** in practice for meaningful event processing.

## Code Examples

### Accept DataWorks Event - curl - all

```bash
POST /api/v1/workspaces/action/acceptdataworksevent HTTP/1.1
Host: api.aliyun.com
Content-Type: application/json

{
  "MessageId": "539306ba-*****-41a0-****-6dc81060985c",
  "Data": {
    "eventCode": "d****ct",
    "projectId": "8***6",
    "tenantId": 4*******8,
    "operator": "115*****901"
  }
}
```

### Basic Event Handler Skeleton - Python - china

```python
import json
from http.server import BaseHTTPRequestHandler, HTTPServer

class DataWorksEventHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        event = json.loads(post_data.decode('utf-8'))
        
        # Extract key fields
        message_id = event.get("MessageId")
        data = event.get("Data")
        
        # Process event (e.g., log, trigger workflow)
        print(f"Received event {message_id} with data: {data}")
        
        # Return success response
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        response = json.dumps({"requestId": "ADF6D849-*****-7E7030F0CE53"})
        self.wfile.write(response.encode())

if __name__ == "__main__":
    server = HTTPServer(('localhost', 8080), DataWorksEventHandler)
    server.serve_forever()
```

### Simulated DataWorks Callback - Python - international

```python
import requests

url = "https://api.alibabacloud.com/api/AIWorkSpace/2021-02-04/AcceptDataworksEvent"
payload = {
    "MessageId": "test-message-12345",
    "Data": {
        "eventCode": "project_deployed",
        "projectId": "98765",
        "tenantId": 12345678,
        "operator": "user@example.com"
    }
}

response = requests.post(url, json=payload)
print("Status:", response.status_code)
print("Response:", response.json())
```

### Minimal Validation Handler - Java - all

```java
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.OutputStream;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

import java.net.InetSocketAddress;

public class EventIntegrationHandler implements HttpHandler {
    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        if ("POST".equals(exchange.getRequestMethod())) {
            String requestBody = new String(exchange.getRequestBody().readAllBytes());
            JsonNode event = mapper.readTree(requestBody);
            
            if (!event.has("MessageId") || !event.has("Data")) {
                exchange.sendResponseHeaders(400, -1);
                return;
            }

            String response = "{\"requestId\": \"REQ-12345-ABCDE\"}";
            exchange.getResponseHeaders().set("Content-Type", "application/json");
            exchange.sendResponseHeaders(200, response.length());
            OutputStream os = exchange.getResponseBody();
            os.write(response.getBytes());
            os.close();
        } else {
            exchange.sendResponseHeaders(405, -1);
        }
    }

    public static void main(String[] args) throws IOException {
        HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
        server.createContext("/acceptdataworksevent", new EventIntegrationHandler());
        server.start();
    }
}
```

## Response Format

```json
{
  "requestId": "ADF6D849-*****-7E7030F0CE53"
}
```

**Key Fields**:
- `requestId` — Unique identifier for the processed request, useful for tracing and logging.

## Error Handling

| Error Code | Description | Recommended Action |
|------------|-------------|---------------------|
| 400 | Bad Request: The request body is malformed or missing required fields. | Validate JSON structure and ensure `MessageId` and `Data` are present. |
| 401 | Unauthorized: Authentication failed or missing credentials. | Verify that the call originates from an authorized DataWorks context; this error is rare for internal calls. |
| 403 | Forbidden: The caller does not have permission to access this endpoint. | Confirm network policies allow traffic from DataWorks; this endpoint is not publicly accessible. |
| 429 | Too Many Requests: Rate limit exceeded. Wait before retrying. | Implement exponential backoff; though uncommon, transient spikes may trigger this. |
| 500 | Internal Server Error: An unexpected error occurred on the server side. | Retry with jitter; contact support if persistent. |
| 502 | Bad Gateway: The server received an invalid response from upstream. | Likely transient; retry after short delay. |
| 503 | Service Unavailable: The service is temporarily unavailable. | Retry later; service may be undergoing maintenance. |

## Common Questions

Q: Is this API publicly available for third-party integrations?
A: No. This endpoint is designed exclusively for internal communication between Alibaba Cloud DataWorks and PAI. It is not intended for external developers or public consumption.

Q: Do I need an API key or access token to call this endpoint?
A: Not in standard operation. The integration relies on trusted service-to-service communication within Alibaba Cloud infrastructure. Explicit credentials are not used.

Q: What should I do if I receive a 403 error?
A: Ensure your request is originating from a legitimate DataWorks extension point invocation. Direct manual calls from outside Alibaba Cloud’s trusted environment will be blocked.

Q: Can I use this endpoint to send custom events to PAI?
A: No. This endpoint only accepts events generated by DataWorks through its official extension point mechanism. Custom payloads may be rejected or ignored.

Q: How can I test this integration during development?
A: Use the provided curl or Python examples to simulate DataWorks payloads, but note that production usage requires proper service linkage within Alibaba Cloud.

## Pricing & Billing

### Billing Model
Per-request billing, but **free of charge** for all usage.

### Price Reference

| Tier | Input Price | Output Price | Other Fees |
|------|-------------|--------------|-----------|
| default | Free | Free | None |

### Free Tier
This interface is for internal system calls and is not billed.

### Usage Limits
No explicit quotas, but subject to overall service capacity and implicit rate limits.

### Billing Notes
This interface is exclusively used for internal event communication between PAI and DataWorks. It is not publicly exposed and incurs no costs.