Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:30:10 +08:00
commit f0bd18fb4e
824 changed files with 331919 additions and 0 deletions

View File

@@ -0,0 +1,883 @@
# Benchling REST API Endpoints Reference
## Base URL
All API requests use the base URL format:
```
https://{tenant}.benchling.com/api/v2
```
Replace `{tenant}` with your Benchling tenant name.
## API Versioning
Current API version: `v2` (2025-10-07)
The API version is specified in the URL path. Benchling maintains backward compatibility within a major version.
## Authentication
All requests require authentication via HTTP headers:
**API Key (Basic Auth):**
```bash
curl -X GET \
https://your-tenant.benchling.com/api/v2/dna-sequences \
-u "your_api_key:"
```
**OAuth Bearer Token:**
```bash
curl -X GET \
https://your-tenant.benchling.com/api/v2/dna-sequences \
-H "Authorization: Bearer your_access_token"
```
## Common Headers
```
Authorization: Bearer {token}
Content-Type: application/json
Accept: application/json
```
## Response Format
All responses follow a consistent JSON structure:
**Single Resource:**
```json
{
"id": "seq_abc123",
"name": "My Sequence",
"bases": "ATCGATCG",
...
}
```
**List Response:**
```json
{
"results": [
{"id": "seq_1", "name": "Sequence 1"},
{"id": "seq_2", "name": "Sequence 2"}
],
"nextToken": "token_for_next_page"
}
```
## Pagination
List endpoints support pagination:
**Query Parameters:**
- `pageSize`: Number of items per page (default: 50, max: 100)
- `nextToken`: Token from previous response for next page
**Example:**
```bash
curl -X GET \
"https://your-tenant.benchling.com/api/v2/dna-sequences?pageSize=50&nextToken=abc123"
```
## Error Responses
**Format:**
```json
{
"error": {
"type": "NotFoundError",
"message": "DNA sequence not found",
"userMessage": "The requested sequence does not exist or you don't have access"
}
}
```
**Common Status Codes:**
- `200 OK`: Success
- `201 Created`: Resource created
- `400 Bad Request`: Invalid parameters
- `401 Unauthorized`: Missing or invalid credentials
- `403 Forbidden`: Insufficient permissions
- `404 Not Found`: Resource doesn't exist
- `422 Unprocessable Entity`: Validation error
- `429 Too Many Requests`: Rate limit exceeded
- `500 Internal Server Error`: Server error
## Core Endpoints
### DNA Sequences
**List DNA Sequences:**
```http
GET /api/v2/dna-sequences
Query Parameters:
- pageSize: integer (default: 50, max: 100)
- nextToken: string
- folderId: string
- schemaId: string
- name: string (filter by name)
- modifiedAt: string (ISO 8601 date)
```
**Get DNA Sequence:**
```http
GET /api/v2/dna-sequences/{sequenceId}
```
**Create DNA Sequence:**
```http
POST /api/v2/dna-sequences
Body:
{
"name": "My Plasmid",
"bases": "ATCGATCG",
"isCircular": true,
"folderId": "fld_abc123",
"schemaId": "ts_abc123",
"fields": {
"gene_name": {"value": "GFP"},
"resistance": {"value": "Kanamycin"}
},
"entityRegistryId": "src_abc123", // optional for registration
"namingStrategy": "NEW_IDS" // optional for registration
}
```
**Update DNA Sequence:**
```http
PATCH /api/v2/dna-sequences/{sequenceId}
Body:
{
"name": "Updated Plasmid",
"fields": {
"gene_name": {"value": "mCherry"}
}
}
```
**Archive DNA Sequence:**
```http
POST /api/v2/dna-sequences:archive
Body:
{
"dnaSequenceIds": ["seq_abc123"],
"reason": "Deprecated construct"
}
```
### RNA Sequences
**List RNA Sequences:**
```http
GET /api/v2/rna-sequences
```
**Get RNA Sequence:**
```http
GET /api/v2/rna-sequences/{sequenceId}
```
**Create RNA Sequence:**
```http
POST /api/v2/rna-sequences
Body:
{
"name": "gRNA-001",
"bases": "AUCGAUCG",
"folderId": "fld_abc123",
"fields": {
"target_gene": {"value": "TP53"}
}
}
```
**Update RNA Sequence:**
```http
PATCH /api/v2/rna-sequences/{sequenceId}
```
**Archive RNA Sequence:**
```http
POST /api/v2/rna-sequences:archive
```
### Amino Acid (Protein) Sequences
**List AA Sequences:**
```http
GET /api/v2/aa-sequences
```
**Get AA Sequence:**
```http
GET /api/v2/aa-sequences/{sequenceId}
```
**Create AA Sequence:**
```http
POST /api/v2/aa-sequences
Body:
{
"name": "GFP Protein",
"aminoAcids": "MSKGEELFTGVVPILVELDGDVNGHKF",
"folderId": "fld_abc123"
}
```
### Custom Entities
**List Custom Entities:**
```http
GET /api/v2/custom-entities
Query Parameters:
- schemaId: string (required to filter by type)
- pageSize: integer
- nextToken: string
```
**Get Custom Entity:**
```http
GET /api/v2/custom-entities/{entityId}
```
**Create Custom Entity:**
```http
POST /api/v2/custom-entities
Body:
{
"name": "HEK293T-Clone5",
"schemaId": "ts_cellline_abc",
"folderId": "fld_abc123",
"fields": {
"passage_number": {"value": "15"},
"mycoplasma_test": {"value": "Negative"}
}
}
```
**Update Custom Entity:**
```http
PATCH /api/v2/custom-entities/{entityId}
Body:
{
"fields": {
"passage_number": {"value": "16"}
}
}
```
### Mixtures
**List Mixtures:**
```http
GET /api/v2/mixtures
```
**Create Mixture:**
```http
POST /api/v2/mixtures
Body:
{
"name": "LB-Amp Media",
"folderId": "fld_abc123",
"schemaId": "ts_mixture_abc",
"ingredients": [
{
"componentEntityId": "ent_lb_base",
"amount": {"value": "1000", "units": "mL"}
},
{
"componentEntityId": "ent_ampicillin",
"amount": {"value": "100", "units": "mg"}
}
]
}
```
### Containers
**List Containers:**
```http
GET /api/v2/containers
Query Parameters:
- parentStorageId: string (filter by location/box)
- schemaId: string
- barcode: string
```
**Get Container:**
```http
GET /api/v2/containers/{containerId}
```
**Create Container:**
```http
POST /api/v2/containers
Body:
{
"name": "Sample-001",
"schemaId": "cont_schema_abc",
"barcode": "CONT001",
"parentStorageId": "box_abc123",
"fields": {
"concentration": {"value": "100 ng/μL"},
"volume": {"value": "50 μL"}
}
}
```
**Update Container:**
```http
PATCH /api/v2/containers/{containerId}
Body:
{
"fields": {
"volume": {"value": "45 μL"}
}
}
```
**Transfer Container:**
```http
POST /api/v2/containers:transfer
Body:
{
"containerIds": ["cont_abc123"],
"destinationStorageId": "box_xyz789"
}
```
**Check Out Container:**
```http
POST /api/v2/containers:checkout
Body:
{
"containerIds": ["cont_abc123"],
"comment": "Taking to bench"
}
```
**Check In Container:**
```http
POST /api/v2/containers:checkin
Body:
{
"containerIds": ["cont_abc123"],
"locationId": "bench_loc_abc"
}
```
### Boxes
**List Boxes:**
```http
GET /api/v2/boxes
Query Parameters:
- parentStorageId: string
- schemaId: string
```
**Get Box:**
```http
GET /api/v2/boxes/{boxId}
```
**Create Box:**
```http
POST /api/v2/boxes
Body:
{
"name": "Freezer-A-Box-01",
"schemaId": "box_schema_abc",
"parentStorageId": "loc_freezer_a",
"barcode": "BOX001"
}
```
### Locations
**List Locations:**
```http
GET /api/v2/locations
```
**Get Location:**
```http
GET /api/v2/locations/{locationId}
```
**Create Location:**
```http
POST /api/v2/locations
Body:
{
"name": "Freezer A - Shelf 2",
"parentStorageId": "loc_freezer_a",
"barcode": "LOC-A-S2"
}
```
### Plates
**List Plates:**
```http
GET /api/v2/plates
```
**Get Plate:**
```http
GET /api/v2/plates/{plateId}
```
**Create Plate:**
```http
POST /api/v2/plates
Body:
{
"name": "PCR-Plate-001",
"schemaId": "plate_schema_abc",
"barcode": "PLATE001",
"wells": [
{"position": "A1", "entityId": "ent_abc"},
{"position": "A2", "entityId": "ent_xyz"}
]
}
```
### Entries (Notebook)
**List Entries:**
```http
GET /api/v2/entries
Query Parameters:
- folderId: string
- schemaId: string
- modifiedAt: string
```
**Get Entry:**
```http
GET /api/v2/entries/{entryId}
```
**Create Entry:**
```http
POST /api/v2/entries
Body:
{
"name": "Experiment 2025-10-20",
"folderId": "fld_abc123",
"schemaId": "entry_schema_abc",
"fields": {
"objective": {"value": "Test gene expression"},
"date": {"value": "2025-10-20"}
}
}
```
**Update Entry:**
```http
PATCH /api/v2/entries/{entryId}
Body:
{
"fields": {
"results": {"value": "Successful expression"}
}
}
```
### Workflow Tasks
**List Workflow Tasks:**
```http
GET /api/v2/tasks
Query Parameters:
- workflowId: string
- statusIds: string[] (comma-separated)
- assigneeId: string
```
**Get Task:**
```http
GET /api/v2/tasks/{taskId}
```
**Create Task:**
```http
POST /api/v2/tasks
Body:
{
"name": "PCR Amplification",
"workflowId": "wf_abc123",
"assigneeId": "user_abc123",
"schemaId": "task_schema_abc",
"fields": {
"template": {"value": "seq_abc123"},
"priority": {"value": "High"}
}
}
```
**Update Task:**
```http
PATCH /api/v2/tasks/{taskId}
Body:
{
"statusId": "status_complete_abc",
"fields": {
"completion_date": {"value": "2025-10-20"}
}
}
```
### Folders
**List Folders:**
```http
GET /api/v2/folders
Query Parameters:
- projectId: string
- parentFolderId: string
```
**Get Folder:**
```http
GET /api/v2/folders/{folderId}
```
**Create Folder:**
```http
POST /api/v2/folders
Body:
{
"name": "2025 Experiments",
"parentFolderId": "fld_parent_abc",
"projectId": "proj_abc123"
}
```
### Projects
**List Projects:**
```http
GET /api/v2/projects
```
**Get Project:**
```http
GET /api/v2/projects/{projectId}
```
### Users
**Get Current User:**
```http
GET /api/v2/users/me
```
**List Users:**
```http
GET /api/v2/users
```
**Get User:**
```http
GET /api/v2/users/{userId}
```
### Teams
**List Teams:**
```http
GET /api/v2/teams
```
**Get Team:**
```http
GET /api/v2/teams/{teamId}
```
### Schemas
**List Schemas:**
```http
GET /api/v2/schemas
Query Parameters:
- entityType: string (e.g., "dna_sequence", "custom_entity")
```
**Get Schema:**
```http
GET /api/v2/schemas/{schemaId}
```
### Registries
**List Registries:**
```http
GET /api/v2/registries
```
**Get Registry:**
```http
GET /api/v2/registries/{registryId}
```
## Bulk Operations
### Batch Archive
**Archive Multiple Entities:**
```http
POST /api/v2/{entity-type}:archive
Body:
{
"{entity}Ids": ["id1", "id2", "id3"],
"reason": "Cleanup"
}
```
### Batch Transfer
**Transfer Multiple Containers:**
```http
POST /api/v2/containers:bulk-transfer
Body:
{
"transfers": [
{"containerId": "cont_1", "destinationId": "box_a"},
{"containerId": "cont_2", "destinationId": "box_b"}
]
}
```
## Async Operations
Some operations return task IDs for async processing:
**Response:**
```json
{
"taskId": "task_abc123"
}
```
**Check Task Status:**
```http
GET /api/v2/tasks/{taskId}
Response:
{
"id": "task_abc123",
"status": "RUNNING", // or "SUCCEEDED", "FAILED"
"message": "Processing...",
"response": {...} // Available when status is SUCCEEDED
}
```
## Field Value Format
Custom schema fields use a specific format:
**Simple Value:**
```json
{
"field_name": {
"value": "Field Value"
}
}
```
**Dropdown:**
```json
{
"dropdown_field": {
"value": "Option1" // Must match exact option name
}
}
```
**Date:**
```json
{
"date_field": {
"value": "2025-10-20" // Format: YYYY-MM-DD
}
}
```
**Entity Link:**
```json
{
"entity_link_field": {
"value": "seq_abc123" // Entity ID
}
}
```
**Numeric:**
```json
{
"numeric_field": {
"value": "123.45" // String representation
}
}
```
## Rate Limiting
**Limits:**
- Default: 100 requests per 10 seconds per user/app
- Rate limit headers included in responses:
- `X-RateLimit-Limit`: Total allowed requests
- `X-RateLimit-Remaining`: Remaining requests
- `X-RateLimit-Reset`: Unix timestamp when limit resets
**Handling 429 Responses:**
```json
{
"error": {
"type": "RateLimitError",
"message": "Rate limit exceeded",
"retryAfter": 5 // Seconds to wait
}
}
```
## Filtering and Searching
**Common Query Parameters:**
- `name`: Partial name match
- `modifiedAt`: ISO 8601 datetime
- `createdAt`: ISO 8601 datetime
- `schemaId`: Filter by schema
- `folderId`: Filter by folder
- `archived`: Boolean (include archived items)
**Example:**
```bash
curl -X GET \
"https://tenant.benchling.com/api/v2/dna-sequences?name=plasmid&folderId=fld_abc&archived=false"
```
## Best Practices
### Request Efficiency
1. **Use appropriate page sizes:**
- Default: 50 items
- Max: 100 items
- Adjust based on needs
2. **Filter on server-side:**
- Use query parameters instead of client filtering
- Reduces data transfer and processing
3. **Batch operations:**
- Use bulk endpoints when available
- Archive/transfer multiple items in one request
### Error Handling
```javascript
// Example error handling
async function fetchSequence(id) {
try {
const response = await fetch(
`https://tenant.benchling.com/api/v2/dna-sequences/${id}`,
{
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
}
);
if (!response.ok) {
if (response.status === 429) {
// Rate limit - retry with backoff
const retryAfter = response.headers.get('Retry-After');
await sleep(retryAfter * 1000);
return fetchSequence(id);
} else if (response.status === 404) {
return null; // Not found
} else {
throw new Error(`API error: ${response.status}`);
}
}
return await response.json();
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}
```
### Pagination Loop
```javascript
async function getAllSequences() {
let allSequences = [];
let nextToken = null;
do {
const url = new URL('https://tenant.benchling.com/api/v2/dna-sequences');
if (nextToken) {
url.searchParams.set('nextToken', nextToken);
}
url.searchParams.set('pageSize', '100');
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
const data = await response.json();
allSequences = allSequences.concat(data.results);
nextToken = data.nextToken;
} while (nextToken);
return allSequences;
}
```
## References
- **API Documentation:** https://benchling.com/api/reference
- **Interactive API Explorer:** https://your-tenant.benchling.com/api/reference (requires authentication)
- **Changelog:** https://docs.benchling.com/changelog