Tất cả hướng dẫn

Trợ lý AI

Hướng dẫn nhanh API: tải lên, kiểm tra, báo giá

Các lệnh đưa file bo mạch đến báo cáo kiểm tra file và bản xem trước giá, bằng curl và ứng dụng JavaScript, cùng các lỗi sẽ gặp.

Dành cho trợ lý AICập nhật 2026-11-10Đọc 6 phútMarkdown thô cho trợ lý AI

Trước khi bắt đầu

API hoạt động không cần tài khoản thông qua phiên khách. API nằm tại địa chỉ của chính trang web dưới /api. Cần đặt một lần:

API=https://dev.uliketechnology.com/api
F=board.zip

board.zip là file zip phẳng chứa file Gerber và file khoan. Về nội dung cần có trong file, xem File cho sản xuất và lắp ráp. Các ví dụ cần curl và jq.

Mọi yêu cầu đến API sau phiên khách đều dùng Authorization: Bearer <token>. Mọi lỗi đều có cùng dạng:

{ "error": { "code": "VALIDATION_FAILED", "message": "…", "details": {}, "requestId": "…" } }

Cần phân nhánh theo code. message dành cho nhà phát triển.

Năm hình nhỏ theo thứ tự: chìa khóa, file đi đến địa chỉ tải lên, đồng hồ cát, trang báo cáo có các phát hiện, và nhãn giá
  1. Phiên khách: token chỉ hiển thị một lần.
  2. Tải lên: thực hiện PUT file zip đến địa chỉ API chỉ định, với các tiêu đề API chỉ định.
  3. Hoàn tất, sau đó thăm dò cho đến khi phân tích xong.
  4. Báo cáo: các phát hiện, kiểm tra nào đã chạy và kiểm tra nào chưa chạy.
  5. Bản xem trước báo giá.

Quy trình bằng curl

Đọc những gì có thể đặt hàng. Bước này không cần token:

curl -s $API/v1/capabilities | jq '.options[].id'

Mở phiên khách. Token chỉ hiển thị một lần và có hiệu lực 30 ngày:

T=$(curl -s -X POST $API/v1/guest-sessions | jq -r .token)

Thông báo file. Câu trả lời có uploadId, designId, uploadUrl và requiredHeaders:

J=$(curl -s -X POST $API/v1/uploads -H "authorization: Bearer $T" -H 'content-type: application/json' \
  -d "{\"fileName\":\"board.zip\",\"sizeBytes\":$(stat -c %s $F),\"sha256\":\"$(sha256sum $F | cut -d' ' -f1)\",\"purpose\":\"design\"}")

Gửi file đến địa chỉ được nêu trong câu trả lời, với mọi tiêu đề trong requiredHeaders (loại nội dung, độ dài và mã kiểm tra; thiếu các tiêu đề này, việc tải lên bị từ chối với 403). Sau đó hoàn tất việc tải lên:

curl -s -X PUT --data-binary @$F \
  $(echo $J | jq -r '.requiredHeaders | to_entries[] | "-H \(.key):\(.value)"') \
  "$(echo $J | jq -r .uploadUrl)"
curl -s -X POST $API/v1/uploads/$(echo $J | jq -r .uploadId)/complete -H "authorization: Bearer $T" | jq .design.status

Trạng thái ban đầu là analysing. Cần đọc thiết kế cho đến khi trạng thái thay đổi. Khi trạng thái là ready, báo cáo nằm trong câu trả lời:

D=$(echo $J | jq -r .designId)
curl -s $API/v1/designs/$D -H "authorization: Bearer $T" | jq '.design.status, .report.headline, .report.counts'

Tiêu đề chính là no_problems_in_checks_run, problems_found hoặc could_not_check. Cần đọc cả checksRun và checksNotRun: kiểm tra chưa chạy không phải là đạt. Các trạng thái khác là needs_mapping (đặt các lớp bằng PUT /v1/designs/{designId}/layer-mapping), needs_engineer và rejected.

Yêu cầu bản xem trước giá. selection và destinationCountry là bắt buộc; selection trống sẽ dùng giá trị mặc định:

curl -s -X POST $API/v1/quote-previews -H "authorization: Bearer $T" -H 'content-type: application/json' \
  -d "{\"designId\":\"$D\",\"quantities\":{\"boardsFabricated\":10,\"boardsAssembled\":0},\"selection\":{},\"destinationCountry\":\"DE\"}" \
  | jq '.mode, .reviewReasons, .totalMinor'

mode là instant (giá giữ nguyên như hiển thị) hoặc review (kỹ sư xác nhận); reviewReasons cho biết lý do. totalMinor tính theo đơn vị nhỏ nhất của currency trong câu trả lời, và vắng mặt khi kỹ sư phải báo giá công việc. Để lưu báo giá, POST /v1/quotes dùng cùng nội dung.

Quy trình tương tự bằng ứng dụng JavaScript

Ứng dụng khách @ulike/sdk bao bọc các tuyến này. Ứng dụng chưa được phát hành dưới dạng gói; đây là dạng của nó, để có thể viết các lệnh tương tự bằng fetch. Tên phương thức:

import { createClient } from '@ulike/sdk';

let token;
const api = createClient({ baseUrl: 'https://dev.uliketechnology.com/api', token: () => token });

const caps = await api.capabilities();
token = (await api.createGuestSession()).token;
const started = await api.uploadDesign({ name: 'board.zip', bytes }); // announce, PUT, complete
const view = await api.waitForDesign(started.design.id); // polls getDesign
const preview = await api.previewQuote({
  designId: view.design.id,
  quantities: { boardsFabricated: 10, boardsAssembled: 0 },
  selection: {},
  destinationCountry: 'DE',
});

Các phương thức còn lại là createUpload, completeUpload, getDesign, setLayerMapping, validateDesign, getValidation, waitForValidation, createQuote, getQuote và reviseQuote. Lỗi được ném ra dưới dạng ApiClientError với status và code.

Kiểm tra cho một đơn hàng

Báo cáo nhận được sau khi tải lên được tạo chỉ từ file. Để kiểm tra file so với một đơn hàng, cần gọi POST /v1/designs/{designId}/validations (validateDesign) với order chứa quantities và selection. Câu trả lời là một trạng thái: running, failed hoặc done. Trong khi running, cần đọc GET /v1/validations/{reportId} (getValidation) mỗi một hoặc hai giây cho đến khi trạng thái là done.

Vòng lặp ba bước: tải file lên, đọc báo cáo, sửa và tải lên lại; một mũi tên rời vòng lặp đến dấu tích khi file sạch
  1. Tải lên file zip.
  2. Đọc báo cáo.
  3. Sửa và tải lên dưới dạng thiết kế mới. Cần dừng lại và hỏi người phụ trách khi việc sửa đổi làm thay đổi chức năng, giá hoặc thời gian giao hàng.
  4. File sạch: chạy kiểm tra cho đơn hàng.

Báo giá hoặc bản xem trước với các tùy chọn mang theo giới hạn khác (đồng dày hơn, độ dày khác) cần một kiểm tra cho lựa chọn đó. Nếu chưa có kiểm tra nào, một kiểm tra sẽ được bắt đầu, và bản xem trước mang lý do kiểm tra file_check_pending cùng một check với reportId của nó. Giá được hiển thị ngay, nhưng báo giá vẫn ở trạng thái review cho đến khi kiểm tra đó hoàn tất. Cần đọc kiểm tra như trên, sau đó yêu cầu lại bản xem trước.

Các lỗi sẽ gặp

Mã Trạng thái Ý nghĩa Cần làm gì
DESIGN_NOT_READY 422 Thiết kế vẫn đang được đọc (details.status cho biết trạng thái nào), hoặc chưa có báo cáo. Cần đọc thiết kế cho đến khi trạng thái không còn là analysing, sau đó yêu cầu lại.
VALIDATION_FAILED 400 Yêu cầu không có dạng mong đợi, hoặc nêu một tùy chọn hay giá trị mà danh mục không có. details liệt kê các vấn đề. Cần sửa trường được nêu trong details và gửi lại. Lấy mã tùy chọn và giá trị từ GET /v1/capabilities.
NOT_MANUFACTURABLE 422 Lựa chọn là thứ nhà máy không sản xuất. details.because mang các lý do. Cần thay đổi lựa chọn; không thử lại cùng một lựa chọn. Cần hỏi người phụ trách nếu thay đổi sẽ làm thay đổi bo mạch.
ANONYMOUS_BUDGET_SPENT 429 Hạn mức hằng ngày khi không có tài khoản đã dùng hết. details.resetsOn là ngày. Cần dừng lại. Cần thông báo cho người phụ trách; họ có thể đăng nhập hoặc chờ đến ngày đó.
REVISION_CONFLICT 409 Một bản sửa đổi nêu một cơ sở không còn là đầu của báo giá. details mang cả hai đầu. Cần đọc đầu bằng GET /v1/quotes/{quoteId}, áp dụng lại thay đổi trên đó, và gửi lại.

Cũng có thể gặp DESIGN_REJECTED (việc tải lên bị từ chối; xem details.reason), UNAUTHENTICATED khi token thiếu hoặc sai (token sai bị từ chối ngay cả trên các tuyến công khai), và FEATURE_DISABLED cho tuyến chưa mở.

Hạn mức hằng ngày khi không có tài khoản

Phiên khách có hạn mức tính toán hằng ngày. Việc tải lên và các kiểm tra đã bắt đầu tốn nhiều hơn một lần đọc thông thường, và việc mở nhiều phiên khách từ một địa chỉ mạng cũng được tính. Kiểm tra mà trang web tự bắt đầu cho một lựa chọn mới được tính vào cùng hạn mức. Khi hạn mức đã dùng hết, sẽ nhận được ANONYMOUS_BUDGET_SPENT kèm ngày hạn mức được đặt lại. Người gọi đã đăng nhập không bị tính theo cách này.

Những gì API chưa làm được hiện nay: đặt hàng, thanh toán, khóa API và đăng nhập cho tác nhân là dự kiến và chưa có sẵn. Máy chủ MCP dự kiến được mô tả trong MCP là gì và cách tác nhân đặt hàng.