Τεκμηρίωση API
Στείλτε αρχεία από τα δικά σας εργαλεία (σενάρια, προγράμματα, διακομιστές): δημιουργήστε μια μεταφορά, ανεβάστε τα αρχεία σε τμήματα, πάρτε τον σύνδεσμο.
Κλειδί διαθέσιμο με τα πακέτα Pro και Business, στο Ο λογαριασμός μου › API. Τιμές
Ταυτοποίηση
Δημιουργήστε ένα κλειδί στο Ο λογαριασμός μου › API και στείλτε το στην κεφαλίδα Authorization κάθε αιτήματος. Κρατήστε το μυστικό: δίνει πρόσβαση στις μεταφορές σας. Ένα διαγραμμένο κλειδί σταματά αμέσως να λειτουργεί.
Authorization: Bearer mlk_… Αν το εργαλείο ή η φιλοξενία σας δεν μεταβιβάζει την κεφαλίδα Authorization, στείλτε το ίδιο κλειδί στην κεφαλίδα X-API-Key:
X-API-Key: mlk_… 120 αιτήματα ανά λεπτό ανά κλειδί. Μέγεθος, αριθμός αρχείων και διάρκεια: σύμφωνα με το πακέτο σας.
Αποστολή αρχείων σε τρία βήματα
1. Δημιουργία της μεταφοράς
Δώστε τη λίστα των αρχείων (όνομα και μέγεθος σε byte). Με το «recipients», κάθε παραλήπτης λαμβάνει email· χωρίς παραλήπτες, παίρνετε έναν σύνδεσμο για κοινοποίηση. Προαιρετικά: «message», «password», «expire_days», «delete_after_download».
curl -X POST https://misi.link/api/v1/transfers \
-H "Authorization: Bearer $MISILINK_KEY" -H "Content-Type: application/json" \
-d '{"files": [{"name": "film.mov", "size": 5368709120}],
"recipients": ["client@example.com"], "message": "…", "expire_days": 14}' {"ok": true, "id": "aB3dE5fG", "token": "…", "url": "https://misi.link/aB3dE5fG",
"files": [{"id": 101, "name": "film.mov", "size": 5368709120}], "chunk_size": 8388608} 2. Ανέβασμα των αρχείων
Στείλτε κάθε αρχείο σε τμήματα το πολύ «chunk_size» byte, με τη σειρά: το «offset» είναι ο αριθμός byte που έχουν ήδη ληφθεί για το αρχείο. Μετά από διακοπή, το «status» δείχνει από πού να συνεχίσετε (απάντηση 409: συνεχίστε από το «received»). Αν η φιλοξενία ή το τείχος προστασίας σας φιλτράρει τις διευθύνσεις, στείλτε τη θέση στην κεφαλίδα X-Upload-Offset αντί για τη διεύθυνση.
curl -X POST "https://misi.link/api/upload/chunk?id=aB3dE5fG&token=…&file=101&offset=0" \
-H "Content-Type: application/octet-stream" --data-binary @morceau-1.bin
# {"ok": true, "received": 8388608, "done": false}
curl "https://misi.link/api/upload/status?id=aB3dE5fG&token=…" 3. Ολοκλήρωση
Όταν ληφθούν όλα τα αρχεία, ολοκληρώστε: η μεταφορά δημοσιεύεται και τα email αποστέλλονται. Ο σύνδεσμος είναι αυτός της πρώτης απάντησης («url»). Αυτό το βήμα είναι υποχρεωτικό. Στη συνέχεια ο διακομιστής αποθηκεύει τα αρχεία: στο μεταξύ το «status» είναι «finalizing». Μια μεταφορά που ελήφθη ολόκληρη αλλά δεν ολοκληρώθηκε ποτέ ολοκληρώνεται αυτόματα μετά από 30 λεπτά χωρίς δραστηριότητα.
curl -X POST https://misi.link/api/upload/complete -H "Content-Type: application/json" \
-d '{"id": "aB3dE5fG", "token": "…"}'
Απευθείας αποστολή στον αποθηκευτικό χώρο (συνιστάται για μεγάλα αρχεία)
Με «direct»: true, το λογισμικό σας στέλνει το αρχείο απευθείας στον αποθηκευτικό χώρο του misi.link, χωρίς να περνά από τον διακομιστή: μέγιστη ταχύτητα και διαθέσιμο σε λίγα δευτερόλεπτα στο τέλος. Ένα αρχείο ανά μεταφορά (πολλά: συγκεντρώστε τα σε αρχείο συμπίεσης). Χωρίς αυτή την επιλογή, ή αν η απάντηση περιέχει «direct»: null, ανεβάστε τα τμήματα με «chunk» όπως παραπάνω.
- Δημιουργήστε τη μεταφορά με «direct»: true. Η απάντηση δίνει «direct.part_size» (μέγεθος κάθε μέρους, το τελευταίο είναι μικρότερο), «direct.parts» (αριθμός μερών) και «direct.sign».
- Ζητήστε από το «sign» τις υπογεγραμμένες διευθύνσεις (αναγνωριστικό, token και αριθμοί μερών, έως 100 ανά κλήση· ισχύουν 6 ώρες), και στείλτε κάθε μέρος με ένα απλό PUT στη διεύθυνσή του, χωρίς κεφαλίδα ταυτοποίησης. Τα μέρη μπορούν να σταλούν παράλληλα και ξανά μετά από αποτυχία.
- Ολοκληρώστε με «complete». Αν λείπει ένα μέρος, η απάντηση είναι «incomplete» με τη λίστα «missing»: στείλτε ξανά αυτά τα μέρη και καλέστε ξανά το «complete». Κρυπτογράφηση από άκρο σε άκρο: κάθε μέρος είναι μια σειρά ολόκληρων κρυπτογραφημένων τμημάτων, με τη σειρά (δείτε το παράδειγμα).
curl -X POST https://misi.link/api/v1/transfers -H "Authorization: Bearer $MISILINK_KEY" -H "Content-Type: application/json" \
-d '{"files": [{"name": "film.mov", "size": 5368709120}], "direct": true}'
# {…, "direct": {"part_size": 16777216, "parts": 320, "total": 5368709120, "sign": "https://misi.link/api/upload/sign"}}
curl -X POST https://misi.link/api/upload/sign -H "Content-Type: application/json" \
-d '{"id": "aB3dE5fG", "token": "…", "parts": [1, 2, 3]}'
# {"ok": true, "urls": {"1": "https://…", "2": "https://…", "3": "https://…"}}
curl -X PUT -H "Content-Type: application/octet-stream" --data-binary @part-1.bin "https://…"
curl -X POST https://misi.link/api/upload/complete -H "Content-Type: application/json" -d '{"id": "aB3dE5fG", "token": "…"}'
# {"ok": false, "error": "incomplete", "missing": [2]}
Κρυπτογράφηση από άκρο σε άκρο (προαιρετική)
Το λογισμικό σας κρυπτογραφεί το αρχείο πριν το στείλει: το misi.link λαμβάνει και αποθηκεύει μόνο δυσανάγνωστα δεδομένα. Το κλειδί δεν αποστέλλεται ποτέ στον διακομιστή: βρίσκεται στον σύνδεσμο, μετά το «#». Ο παραλήπτης κατεβάζει και αποκρυπτογραφεί στο πρόγραμμα περιήγησης, στη συνηθισμένη σελίδα.
- Δημιουργήστε τυχαία ένα κλειδί 16 byte και κατόπιν τη μεταφορά με «e2e»: true και ένα μόνο αρχείο (το μη κρυπτογραφημένο μέγεθός του σε byte). Για πολλά αρχεία, συγκεντρώστε τα πρώτα σε ένα αρχείο συμπίεσης.
- Κλειδί κρυπτογράφησης: HKDF-SHA-256 του κλειδιού (salt «misilink-e2e-v1», info = αναγνωριστικό της μεταφοράς, 16 byte), για AES-GCM.
- Χωρίστε το αρχείο σε τμήματα 4 MiB (4.194.304 byte). Τμήμα αρ. i: nonce = 4 μηδενικά byte και μετά το i σε 8 byte (big-endian)· συσχετισμένα δεδομένα = i σε 8 byte και μετά 1 byte (1 για το τελευταίο τμήμα, αλλιώς 0). Κάθε κρυπτογραφημένο τμήμα έχει 16 byte περισσότερα: ανεβάστε αυτά τα byte με «chunk», με τη σειρά (συνολικά «e2e.encrypted_size»), και ολοκληρώστε με «complete».
- Συνιστάται: «e2e_verify» = HKDF-SHA-256 του κλειδιού (ίδιο salt, info «misilink-verify», 32 byte) σε base64url. Έτσι το misi.link απορρίπτει μια λήψη με λάθος κλειδί, χωρίς να γνωρίζει ποτέ το σωστό.
- Σύνδεσμος για κοινοποίηση: «url» + «#» + το κλειδί σε base64url (22 χαρακτήρες). Με παραλήπτες («recipients»), προσθέστε «e2e_key» (το κλειδί): το misi.link το φυλάσσει σφραγισμένο για να το βάλει στους συνδέσμους των email.
curl -X POST https://misi.link/api/v1/transfers \
-H "Authorization: Bearer $MISILINK_KEY" -H "Content-Type: application/json" \
-d '{"files": [{"name": "film.mov", "size": 5368709120}], "e2e": true, "e2e_verify": "…"}'
# {"ok": true, "id": "aB3dE5fG", …, "e2e": {"segment": 4194304, "tag": 16, "encrypted_size": 5368729600, "version": 1}} Πλήρες παράδειγμα σε Python (βιβλιοθήκη cryptography):
#!/usr/bin/env python3
# misi.link: end-to-end encrypted upload through the API (Python 3.8+, pip install cryptography)
# The file goes straight to the storage (signed URLs); if direct upload is unavailable, through "chunk".
# Usage: MISILINK_KEY=mlk_... python3 misilink_e2e.py file.mov [https://misi.link]
import base64, json, os, sys, urllib.request
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives.hashes import SHA256
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
SEG, SALT = 4 * 1024 * 1024, b'misilink-e2e-v1'
b64 = lambda b: base64.urlsafe_b64encode(b).rstrip(b'=').decode()
hkdf = lambda ikm, info, n: HKDF(SHA256(), n, SALT, info).derive(ikm)
def call(url, body=None, raw=None, headers=None, method=None, auth=True):
h = dict(headers or {})
if auth:
h['Authorization'] = 'Bearer ' + os.environ['MISILINK_KEY']
data = raw if raw is not None else (json.dumps(body).encode() if body is not None else None)
if data is not None:
h.setdefault('Content-Type', 'application/octet-stream' if raw is not None else 'application/json')
req = urllib.request.Request(url, data=data, headers=h, method=method or ('POST' if data is not None else 'GET'))
with urllib.request.urlopen(req, timeout=600) as r:
body = r.read()
return json.loads(body) if body[:1] == b'{' else {}
def segments(path, key, size):
n = max(1, -(-size // SEG))
with open(path, 'rb') as f:
for i in range(n):
last = i == n - 1
nonce = bytes(4) + i.to_bytes(8, 'big')
aad = i.to_bytes(8, 'big') + (b'\x01' if last else b'\x00')
yield key.encrypt(nonce, f.read(SEG), aad) # SEG bytes in, SEG + 16 bytes out
def send(path, base='https://misi.link'):
size = os.path.getsize(path)
secret = os.urandom(16) # the key: never sent to the server
verify = b64(hkdf(secret, b'misilink-verify', 32)) # lets the server recognise the right key
t = call(base + '/api/v1/transfers', {'files': [{'name': os.path.basename(path), 'size': size}],
'e2e': True, 'e2e_verify': verify, 'direct': True})
key = AESGCM(hkdf(secret, t['id'].encode(), 16))
auth = {'id': t['id'], 'token': t['token']}
d = t.get('direct')
if d: # straight to the storage: parts of d['part_size'] bytes
part, n, urls = b'', 0, {}
def put(n, data):
if str(n) not in urls:
urls.update(call(d['sign'], {**auth, 'parts': list(range(n, min(n + 100, d['parts'] + 1)))})['urls'])
call(urls[str(n)], raw=data, method='PUT', auth=False)
for seg in segments(path, key, size):
part += seg
if len(part) == d['part_size']:
n += 1; put(n, part); part = b''
if part:
n += 1; put(n, part)
else: # through the server
sent = 0
for seg in segments(path, key, size):
r = call(t['upload']['chunk'] + '?id=' + t['id'] + '&token=' + t['token'] + '&file=' + str(t['files'][0]['id']),
raw=seg, headers={'X-Upload-Offset': str(sent)})
sent = r['received']
call(t['upload']['complete'], auth)
return t['url'] + '#' + b64(secret) # the key travels after "#", only in the link
if __name__ == '__main__':
print(send(sys.argv[1], *(sys.argv[2:3] or [])))
Άλλα αιτήματα
GET /api/v1/transfers- Οι μεταφορές σας, 50 ανά σελίδα (?page=2…).
GET /api/v1/transfers/{id}- Μία μεταφορά: κατάσταση, σύνδεσμος, αρχεία, αριθμός λήψεων, ημερομηνία λήξης.
DELETE /api/v1/transfers/{id}- Διαγραφή μεταφοράς (ο σύνδεσμος σταματά να λειτουργεί).
GET /api/v1/me- Ο λογαριασμός σας, το πακέτο σας και τα όριά του, μέγεθος τμημάτων.
Ημερομηνίες σε μορφή ISO 8601 (UTC), μεγέθη σε byte.
Απαντήσεις και σφάλματα
Όλες οι απαντήσεις είναι JSON, με «ok». Σε σφάλμα: «error» (σύντομος κωδικός) και «message». Κωδικοί HTTP: 401 κλειδί που λείπει ή δεν ισχύει, 403 πακέτο χωρίς API, 404 δεν βρέθηκε, 409 τμήμα σε λάθος θέση, 422 το αίτημα απορρίφθηκε, 429 πάρα πολλά αιτήματα (περιμένετε ένα λεπτό).