NAV Navbar
shell ruby javascript php
  • Introduction
  • SDKs
  • Authorization
  • Transferring
  • Errors
  • Changelog
  • Big news: on 2018-09-25 we released a new version (V2) of our API - introducing the Transfer & Board APIs.

    If you're looking for documentation for V2 you can find that here.

    Introduction

    Welcome to WeTransfer's public API! You can use our API to create transfer links and share files and love all over the world.

    Flow Diagram

    1. Authorize

      First, we have to make sure you’re fully authorized to create a new transfer. You do this by sending two authentication headers with the authorize request.

    2. Create a Transfer Object

      Next up, we create an empty transfer object and tell it what items to expect in the next step. This is also where we retrieve the URL for the transfer itself.

    3. Upload each file to Transfer Object

      Then for each file part you request an upload URL that will show you where on Amazon to put it. Repeat until you’ve uploaded all parts and move on to next file.

      for each part
    4. Transfer completed

    SDKs

    Official SDKs

    We make them, you use (and contribute to) them: WeTransfer made SDKs!

    Community Developed SDKs

    You make them, we present them: community made SDKs!

    Authorization

    POST /authorize

    To be able to use our APIs, you must provide a secret api key on every request. You can create a key on our Developer Portal. Please make sure that you keep your API key in a secret place, and it's not shared on CVS repositories or client side code.

    Our APIs expect the API key to be included as a header on every API requests. Please provide the API key using x-api-key header, like in the following example:

    We also require a Content-Type: application/json header on every request, otherwise you will receive an "Unsupported Media Type" error.

    Besides the API Key and the Content-Type header, a JSON Web Token (JWT) must be included on subsequent requests. To retrieve a JWT, send a request, including your API token to the following endpoint:

    curl -X POST \
      https://dev.wetransfer.com/v1/authorize \
      -H "Content-Type: application/json" \
      -H "x-api-key: your_api_key"
    
    require 'we_transfer_client'
    
    # Please keep in mind that authorization is performed when the client is initialized.
    client = WeTransferClient.new(api_key: '# YOUR PRIVATE API KEY GOES HERE'))
    
    const createWTClient = require('@wetransfer/js-sdk');
    
    // Please keep in mind that authorization is performed when the client is initialized.
    const apiClient = await createWTClient('/* YOUR PRIVATE API KEY GOES HERE */');
    
    // When using the SDK, there is no need to call authorize manually.
    // The method is available though, in case you need to access the JWT.
    const auth = await apiClient.authorize();
    
    <?php
    \WeTransfer\Client::setApiKey(getenv['WT_API_KEY']);
    
    // When using the SDK, there is no need to call authorize manually.
    // The method is available though, in case you need to access the JWT.
    $token = \WeTransfer\Client::authorize();
    

    Headers

    name type required description
    x-api-key String Yes Private API key
    Content-Type String Yes must be application/json

    Response

    {
      "success": true,
      "token": "A valid JWT token here"
    }
    
    name type description
    success Boolean Successful request, or not.
    token String A JWT token valid for one year, if authorization went well

    Transferring

    Create a new transfer

    Transfers can be created with or without items. Once the transfer has been created, items can be added at any time.

    curl https://dev.wetransfer.com/v1/transfers \
      -H "Content-Type: application/json" \
      -H "x-api-key: your_api_key" \
      -H "Authorization: Bearer jwt_token" \
      -d '{"name": "My very first transfer!"}'
    
    transfer = client.create_transfer(name: 'My very first transfer!', description: 'Something about cats, most probably.') do |builder|
      builder.add_file(name: File.basename(__FILE__), io: File.open(__FILE__, 'rb'))
      builder.add_file(name: 'cat-picture.jpg', io: StringIO.new('cat-picture'))
      builder.add_file(name: 'README.txt', io: File.open('/path/to/local/readme.txt', 'rb'))
      builder.add_file_at(path: __FILE__)
    end
    
    const transfer = await apiClient.transfer.create({
      name: 'My very first transfer!',
      description: 'Something about cats, most probably.'
    });
    
    <?php
    $transfer = \WeTransfer\Transfer::create(
        'My very first transfer!',
        'Something about cats, most probably.'
    );
    

    POST /transfers

    Headers

    name type required description
    x-api-key String Yes Private API key
    Authorization String Yes Bearer JWT authorization token
    Content-Type String Yes must be application/json

    Parameters

    name type required description
    name String Yes Something about cats or coffee, most probably
    description String No A description, if needed

    Response

    {
      "id": "random-hash",
      "version_identifier": null,
      "state": "uploading",
      "shortened_url": "https://we.tl/s-random-hash",
      "name": "Little kittens",
      "description": null,
      "size": 0,
      "total_items": 0,
      "items": []
    }
    

    Creates a new empty transfer.


    👉🏻 Note: the shortened_url in the response is the URL you will use to access the transfer you create! It is not returned at the end of the upload flow, rather when you create the empty transfer. 👈🏻


    Add items to a transfer

    POST /transfers/{transfer_id}/items

    Once a transfer has been created you can then add items to it.

    curl https://dev.wetransfer.com/v1/transfers/{transfer_id}/items \
      -H "x-api-key: your_api_key" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer jwt_token" \
      -d '{"items": [{"local_identifier": "delightful-cat", "content_identifier": "file", "filename": "kittie.gif", "filesize": 1024}, {"local_identifier":"favourite-site", content_identifier: "web_content", "url":"https://developers.wetransfer.com", "meta":{"title":"My Favourite Developers Portal!"}}]}'
    
    const fileItems = await apiClient.transfer.addFiles(transfer, [{
      filename: 'kittie.gif',
      filesize: 1024
    }]);
    
    const linkItems = await apiClient.transfer.addLinks(transfer, [{
      url: 'https://wetransfer.com',
      meta: {
        title: 'WeTransfer'
      },
    }]);
    
    <?php
    \WeTransfer\Transfer::addLinks($transfer, [
        [
            'url' => 'https://en.wikipedia.org/wiki/Japan',
            'meta' => [
                'title' => 'Japan'
            ]
        ]
    ]);
    
    \WeTransfer\Transfer::addFiles($transfer, [
        [
            'filename' => 'Japan-01.jpg',
            'filesize' => 13370099
        ]
    ]);
    

    Headers

    name type required description
    x-api-key String Yes Private API key
    Authorization String Yes Bearer JWT authorization token
    Content-Type String Yes must be application/json

    Parameters

    name type required description
    items Array(Item) Yes A list of items to send to an existing transfer

    Item object

    An item can be either a file or an URL.

    File object

    name type required description
    filename String Yes The name of the file you want to show on the items list. Must be less than 255 characters!
    filesize Integer Yes File size in bytes. Must be accurate. No fooling. Don't let us down.
    content_identifier String Yes Must be "file".
    local_identifier String Yes Unique identifier to identify the item locally (to your system). Must be less than 36 characters!

    URL object

    name type required description
    url String Yes A complete URL. Must be less than 2000 characters!
    content_identifier String Yes Must be "web_content".
    local_identifier String Yes Unique identifier to identify the item locally (to your system). Must be less than 36 char`acters!
    meta Object Yes You can use this to store the metadata of the URL. For example: "meta": {"title":"The Best URL EVER!"} The complete meta string Must be less than 3000 characters!

    Response

    [{
      "id": "random-hash",
      "content_identifier": "file",
      "local_identifier": "delightful-cat",
      "meta": {
        "multipart_parts": 3,
        "multipart_upload_id": "some.random-id--"
      },
      "name": "kittie.gif",
      "size": 195906,
      "upload_id": "more.random-ids--",
      "upload_expires_at": 1520410633
    },
    {
      "id": "random-hash",
      "content_identifier": "web_content",
      "meta": {
        "title": "WeTransfer"
      },
      "url": "https://wetransfer.com"
    }]
    

    It will return an object for each item you want to add to the transfer. Each item must be split into chunks, and uploaded to a pre-signed S3 URL, provided by the following endpoint.

    Important Chunks must be 6 megabytes in size, except for the very last chunk, which can be smaller. Sending too much or too little data will result in a 400 Bad Request error when you finalize the file.

    Request upload URL

    GET /files/{file_id}/uploads/{part_number}/{multipart_upload_id}

    To be able to upload a file, it must be split into chunks, and uploaded to different presigned URLs. This route can be used to fetch presigned upload URLS for each of a file's parts.

    curl "https://dev.wetransfer.com/v1/files/{file_id}/uploads/{part_number}/{multipart_upload_id}" \
      -H "Content-Type: application/json" \
      -H "x-api-key: your_api_key" \
      -H "Authorization: Bearer jwt_token"
    

    Headers

    name type required description
    x-api-key String Yes Private API key
    Authorization String Yes Bearer JWT authorization token
    Content-Type String Yes must be application/json

    Parameters

    name type required description
    file_id String Yes The public ID of the file to upload, returned when adding items.
    part_number Number Yes Which part number of the file you want to upload. It will be limited to the maximum multipart_parts response.
    multipart_upload_id Number Yes The upload ID issued by AWS S3.

    Responses

    200 (OK)
    {
      "upload_url": "https://presigned-s3-put-url",
      "part_number": 1,
      "upload_id": "an-s3-issued-multipart-upload-id",
      "upload_expires_at": 1519988329
    }
    

    The Response Body contains the upload_url, part_number, upload_id, and upload_expires_at.

    401 (Unauthorized)

    If the requester tries to request an upload URL for a file that is not in one of the requester's transfers, we will respond with 401 UNAUTHORIZED.

    400 (Bad request)

    If a request is made for a part, but no multipart_upload_id is provided; we will respond with a 400 BAD REQUEST as all consecutive parts must be uploaded with the same multipart_upload_id.

    File upload

    PUT {signed_url}

    Please note: errors returned from S3 will be sent as XML, not JSON. If your response parser is expecting a JSON response it may throw an error here. Please see AWS' S3 documentation for more details about specific responses.

    curl -T "./path/to/kittie.gif" "https://signed-s3-upload-url"
    
    // Depending on your application, you will read the file using fs.readFile
    // or it will be a file uploaded to your service.
    const files = [[/* Buffer */], [/* Buffer */]];
    await Promise.all(transferItems.map((item, index) => {
      return apiClient.transfer.uploadFile(item, files[index]);
    }));
    
    <?php
    foreach($transfer->getFiles() as $file) {
      \WeTransfer\File::upload($file, fopen(realpath('./path/to/your/files.jpg'), 'r'));
    }
    

    Complete a file upload

    POST /files/{file_id}/uploads/complete

    After the file upload is successful, the file must be marked as complete.

    curl -X https://dev.wetransfer.com/v1/files/{file_id}/uploads/complete \
      -H "Content-Type: application/json" \
      -H "x-api-key: your_api_key" \
      -H "Authorization: Bearer jwt_token"
    

    Headers

    name type required description
    x-api-key String Yes Private API key
    Authorization String Yes Bearer JWT authorization token
    Content-Type String Yes must be application/json

    Parameters

    name type required description
    file_id String Yes The public ID of the file to upload, returned when adding items.

    Errors

    In working with the WeTransfer API you might come across some errors. Here are some of the most common, and what you can do about them.

    Most common errors

    Error Message Explanation Solution
    Missing Authentication Token {"message":"Missing Authentication Token"} Despite what you might think, this actually just means that you're hitting an endpoint that doesn't exist. Check that you've spelled the endpoint correctly, and remember that our API is versioned - dev.wetransfer.com/authorize won't work, but dev.wetransfer.com/v1/authorize will.
    Forbidden {"message":"Forbidden"} You've forgotten to send us your API key, or it's being improperly sent. Make sure that you're sending your API key with each request - see the example code, or add a header like so: X-API-KEY: <your api key>.
    Unsupported Media Type {"message":"Unsupported Media Type"} You've sent a request to the API without a Content-Type set, or incorrectly set. Make sure that you're sending a Content-Type: application/json header with each request.
    Unsupported HTTP Method {"message":"Unsupported HTTP method"} You've sent a request to an endpoint using the wrong HTTP method. For example, you've sent a POST request to an endpoint that expects a GET. Make sure that you're using the correct HTTP verb for each endpoint.
    API Rate Limit {"message":"Limit Exceeded Exception"} or a 429 response You've exceeded your rate limit. Try again but with fewer requests in a given time period, wait until tomorrow, or even better: email us (developers@wetransfer.com) and we can talk extending the limit.
    Expected X to be Y {"message":"Expected 1200 to be 3243214"} If the size of the file you send does not match the size of the file you told us to expect, you'll see this message when you send a /complete request. Check that you're properly computing the size of the file, or that you're uploading all the required chunks (before sending the complete call).

    A note about file upload errors

    Because file uploads go directly to S3, any errors during this step of the process will be returned in XML. Please see the official S3 documentation for details of individual AWS S3 responses.

    Error codes

    The WeTransfer API uses the following conventional error codes:

    Code Meaning
    400 Bad Request -- Your request is invalid.
    403 Forbidden -- Your API key is wrong.
    404 Not Found -- The specified resource could not be found.
    405 Method Not Allowed -- You tried to access a transfer with an invalid method.
    406 Not Acceptable -- You requested a format that isn't json.
    410 Gone -- The transfer requested has been removed from our servers.
    418 I'm a teapot.
    429 Too Many Requests -- You're requesting too many things! Slow down!
    500 Internal Server Error -- We had a problem with our server. Try again later.
    503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.

    Changelog

    date change api / portal / documentation
    2018-07-25 Clarify shortened_url, copy fixes documentation
    2018-07-24 Add PHP code snippets documentation
    2018-07-18 Clarify a couple of required params and add errors documentation documentation
    2018-07-10 Deprecate TLS 1.0 and 1.1 on developers portal portal
    2018-07-06 Add changelog to documentation documentation
    2018-06-22 Add ability for users to create multiple keys portal
    2018-05-30 Add HSTS header to API endpoints api and portal
    2018-05-14 Release initial version of API to the world all