마크다운과 로컬 이미지가 포함된 ZIP 아카이브를 업로드하세요. 시스템이 에셋을 처리하고 참조를 수정하여 미리보기, 배포 및 후속 워크플로우에 바로 사용할 수 있는 HTML을 생성합니다.
일반적인 API 문서가 아니라 markdown2html 워크플로우에 맞춰 설계되었습니다
상대 경로 이미지 참조가 포함된 Obsidian 및 마크다운 패키지 내보내기에 최적화되어 있습니다.
추가적인 수동 정리 작업 없이 바로 미리보기, 게시 또는 후속 작업에 활용할 수 있는 HTML을 제공합니다.
브랜드 콘텐츠, 지식 베이스 게시 및 배치 워크플로우 전반에서 일관된 출력 스타일을 유지합니다.
아티클과 에셋이 깔끔하게 정리되어 검색, 재사용 및 팀 협업이 용이합니다.
Obsidian, 지식 베이스 또는 로컬 편집 파일의 마크다운 아티클을 ZIP 아카이브로 패키징합니다.
시스템이 이미지 업로드, 참조 교체 및 레이아웃 변환을 자동으로 처리하도록 합니다.
생성된 결과를 게시, 배포, AI 강화 또는 내부 편집 파이프라인에 활용합니다.
아래 섹션은 개발자 콘솔이자 AI 통합을 위한 복사 가능한 핸드오프 문서로 작동합니다.
클릭 한 번으로 API 키를 생성하고, 아래 마크다운 가이드를 복사해 AI 에이전트나 개발팀에 바로 전달하세요.
가져오기 API 키 생성
토큰은 생성 후 한 번만 표시됩니다. 분실 시 폐기 후 다시 생성하세요.
기존 키
생성된 API 키가 없습니다
테마 API 식별자
각 themeId는 에디터에 표시된 테마 이름과 일치합니다. 사람이 읽을 수 있는 이름과 참조 색상이 아래에 나열되어 있습니다.
AI 호환 API 통합 가이드
公众号https://api.imgto.link
POST https://api.imgto.link/uploads/md-importPOST https://api.imgto.link/api/v1/md/importGET https://api.imgto.link/api/v1/md/import/jobs/{jobId}https://api.imgto.link host, so clients only need one public base URL.Use an API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
uploadRelativePathPOST https://api.imgto.link/api/v1/md/importGET https://api.imgto.link/api/v1/md/import/jobs/{jobId} until the job reaches a terminal statusPOST https://api.imgto.link/uploads/md-import
multipart/form-data
archive (required): ZIP file containing one Markdown file and its local image files{
"code": 200,
"data": {
"relativePath": "inbox/2026/03/12/uuid-article-package.zip",
"originalFilename": "article-package.zip",
"size": 345678,
"uploadedAt": "2026-03-12T08:00:00.000Z"
}
}
POST https://api.imgto.link/api/v1/md/import
application/json
{
"uploadRelativePath": "inbox/2026/03/12/uuid-article-package.zip",
"archiveFilename": "article-package.zip",
"archiveSize": 345678,
"themeId": "classic",
"directoryPath": "public/articles/demo",
"entryMarkdown": "docs/index.md",
"saveFolderId": 12,
"mdfileId": 123
}
uploadRelativePath (required): value returned from step 1archiveFilename (required): original zip filenamearchiveSize (optional): archive size in bytesthemeId (optional): theme API name, default is classicdirectoryPath (optional): base upload directory path like public/articles/launch-2026entryMarkdown (optional): specific markdown file path inside the ZIP when there are multiple markdown filessaveFolderId (optional): target markdown folder ID in the editormdfileId (optional): existing markdown article ID. When provided, the import is treated as a replace/update. The old article and its imported images are deleted before the new content is saved{
"code": 202,
"message": "Accepted",
"data": {
"jobId": "mdi_1234567890abcdef",
"status": "QUEUED",
"progress": 0,
"pollUrl": "/api/v1/md/import/jobs/mdi_1234567890abcdef"
}
}
GET https://api.imgto.link/api/v1/md/import/jobs/{jobId}
{
"code": 200,
"message": "Ok",
"data": {
"jobId": "mdi_1234567890abcdef",
"status": "PROCESSING",
"progress": 65,
"currentStage": "processing_images",
"message": "正在处理图片 2/4",
"compensationStatus": "NOT_REQUIRED",
"updatedAt": "2026-03-12T08:01:15.000Z"
}
}
{
"code": 200,
"message": "Ok",
"data": {
"jobId": "mdi_1234567890abcdef",
"status": "SUCCEEDED",
"progress": 100,
"currentStage": "completed",
"message": "导入完成",
"compensationStatus": "NOT_REQUIRED",
"updatedAt": "2026-03-12T08:01:30.000Z",
"result": {
"mdfileId": 123,
"resolvedMarkdown": "# Title\n\n",
"html": "<section>...</section>",
"wechatApiHtml": "<section>...</section>",
"imageDirectoryPath": "public/公众号/my-article",
"savedArticle": {
"id": 123,
"mdfileId": 123,
"title": "My Article",
"folder": {
"id": 9,
"name": "公众号",
"fullPath": "公众号"
}
}
}
}
}
{
"code": 200,
"message": "Ok",
"data": {
"jobId": "mdi_1234567890abcdef",
"status": "FAILED_COMPENSATED",
"progress": 100,
"currentStage": "failed",
"message": "导入失败,已回滚上传图片与用户额度",
"compensationStatus": "COMPLETED",
"updatedAt": "2026-03-12T08:02:00.000Z",
"error": {
"message": "Referenced image not found: ./images/cover.png"
}
}
}
SUCCEEDEDFAILED_COMPENSATEDFAILED_PENDING_COMPENSATION and FAILED_COMPENSATION_ERRORresult is returned only when the job succeedserror is returned when the job failsresult.resolvedMarkdown: Markdown after local image paths are replaced with Imgto.link URLsresult.html: Base rendered HTML for preview or debuggingresult.wechatApiHtml: Recommended HTML for submitting to the WeChat Official Account API content fieldresult.mdfileId: The saved Markdown article ID, returned for convenient reuse in the next replace import requestresult.savedArticle: Saved Markdown article record in the editorresult.savedArticle.mdfileId: Stable article identifier to pass back on the next import if you want to replace this article instead of creating a new oneresult.imageDirectoryPath: Final image upload directory pathcurl -X POST "https://api.imgto.link/uploads/md-import" \
-F "archive=@article-package.zip" \
curl -X POST "https://api.imgto.link/api/v1/md/import" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"uploadRelativePath": "inbox/2026/03/12/uuid-article-package.zip",
"archiveFilename": "article-package.zip",
"archiveSize": 345678,
"themeId": "classic",
"directoryPath": "public/articles/demo"
}'
curl -X GET "https://api.imgto.link/api/v1/md/import/jobs/mdi_1234567890abcdef" \
-H "Authorization: Bearer YOUR_API_KEY"
const uploadFormData = new FormData();
uploadFormData.append("archive", zipFile);
const uploadResponse = await fetch("https://api.imgto.link/uploads/md-import", {
method: "POST",
body: uploadFormData
});
const uploadResult = await uploadResponse.json();
const relativePath = uploadResult.data.relativePath;
const createResponse = await fetch("https://api.imgto.link/api/v1/md/import", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
uploadRelativePath: relativePath,
archiveFilename: uploadResult.data.originalFilename,
archiveSize: uploadResult.data.size,
themeId: "classic",
directoryPath: "public/articles/demo"
})
});
const createResult = await createResponse.json();
const jobId = createResult.data.jobId;
let finalResult = null;
for (;;) {
const pollResponse = await fetch("https://api.imgto.link/api/v1/md/import/jobs/" + jobId, {
method: "GET",
headers: {
Authorization: "Bearer YOUR_API_KEY"
}
});
const pollResult = await pollResponse.json();
const job = pollResult.data;
if (job.status === "SUCCEEDED") {
finalResult = job.result;
break;
}
if (job.status === "FAILED_COMPENSATED") {
throw new Error(job.error?.message || "Import failed");
}
await new Promise((resolve) => setTimeout(resolve, 1800));
}
console.log(finalResult.mdfileId);
console.log(finalResult.resolvedMarkdown);
console.log(finalResult.wechatApiHtml);
console.log(finalResult.savedArticle);
Use the result.savedArticle.mdfileId returned by the previous successful import job.
const replaceResponse = await fetch("https://api.imgto.link/api/v1/md/import", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
uploadRelativePath: uploadedZip.data.relativePath,
archiveFilename: uploadedZip.data.originalFilename,
archiveSize: uploadedZip.data.size,
themeId: "classic",
mdfileId: previousResult.savedArticle.mdfileId
})
});
const replaceResult = await replaceResponse.json();
console.log(replaceResult.data.jobId);
mdfileId omitted: create a new import job using the uploaded ZIPmdfileId provided: force this import to replace that exact articlemdfileId from the final successful poll result and keep using it for future updatesUse result.wechatApiHtml from the completed import job for the content field instead of result.html.
const completedImport = await waitForImportJob(jobId);
const wechatApiHtml = completedImport.result.wechatApiHtml;
const draftPayload = {
articles: [
{
title: completedImport.result.savedArticle?.title || "Imported article",
author: "Your Team",
digest: "",
content: wechatApiHtml,
content_source_url: "",
thumb_media_id: "YOUR_WECHAT_THUMB_MEDIA_ID",
need_open_comment: 0,
only_fans_can_comment: 0
}
]
};
const wechatResponse = await fetch(
"https://api.weixin.qq.com/cgi-bin/draft/add?access_token=YOUR_WECHAT_ACCESS_TOKEN",
{
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(draftPayload)
}
);
const wechatResult = await wechatResponse.json();
console.log(wechatResult);
result.wechatApiHtml for WeChat Official Account API publishingresult.html as the content field if you need output aligned with the website's copy/export flowresult.wechatApiHtml should already point to uploaded Imgto.link assetsaccess_token and thumb_media_idwarm): #ea580c, #333china): #7f1d1d, #292524, #f5f5f4cyber): #ec4899, #a855f7, #3b82f6classic): #07c160, #333ink): #3f3f46, #78716ceditorial): #1f2937, #ef4444wenkai): #57534e, #78716cbusiness): #1e3a8a, #1e40afforest): #059669, #ecfdf5azure): #0ea5e9, #e0f2fecoffee): #78350f, #fffbebneon): #d946ef, #06b6d4red): #be123c, #fff1f2silver): #475569, #e2e8f0minimal): #000, #999morandi): #be185d, #fbcfe8sunny): #f97316, #fbbf24mint): #10b981, #d1fae5autumn): #d97706, #fef3c7lavender): #8b5cf6, #ede9fevintage): #7f1d1d, #fecacanotes): #facc15, #fef08agrey): #374151, #f3f4f6entryMarkdown./images/a.png公众号{directoryPath}/{article-slug}If you give this API to an AI coding assistant, tell it:
"Use the async workflow. First upload the ZIP to https://api.imgto.link/uploads/md-import with multipart/form-data and read data.relativePath, data.originalFilename, and data.size. Then call POST https://api.imgto.link/api/v1/md/import with JSON using uploadRelativePath, archiveFilename, and optional themeId, directoryPath, entryMarkdown, saveFolderId, and mdfileId. Authenticate the control-plane API with Authorization: Bearer YOUR_API_KEY. Then poll GET https://api.imgto.link/api/v1/md/import/jobs/{jobId} until status becomes SUCCEEDED or FAILED_COMPENSATED. On success, read result.resolvedMarkdown, result.wechatApiHtml, result.savedArticle, result.mdfileId, and result.imageDirectoryPath. Prefer result.wechatApiHtml when publishing to the WeChat Official Account API content field."